IOI 2000 Walls Floyd+枚举

Walls

 

PROBLEM

In a country, great walls have been built in such a way that every great wall connects exactly two towns. The great walls do not cross each other. Thus, the country is divided into such regions that to move from one region to another, it is necessary to go through a town or cross a great wall. For any two towns A and B, there is at most one great wall with one end in A and the other in B, and further, it is possible to go from A to B by always walking in a town or along a great wall. The input format implies additional restrictions.

There is a club whose members live in the towns. In each town, there is only one member or there are no members at all. The members want to meet in one of the regions (outside of any town). The members travel riding their bicycles. They do not want to enter any towns, because of the traffic, and they want to cross as few great walls as possible, as it is a lot of trouble. To go to the meeting region, each member needs to cross a number (possibly 0) of great walls. They want to find such an optimal region that the sum of these numbers (crossing-sum, for short) is minimized.

The towns are labeled with integers from 1 to N, where N is the number of towns. In Figure 1, the labeled nodes represent the towns and the lines connecting the nodes represent the great walls. Suppose that there are three members, who live in towns 3, 6, and 9. Then, an optimal meeting region and respective routes for members are shown in Figure 2. The crossing-sum is 2: the member from town 9 has to cross the great wall between towns 2 and 4, and the member from town 6 has to cross the great wall between towns 4 and 7.

You are to write a program which, given the towns, the regions, and the club member home towns, computes an optimal region and the minimal crossing-sum.

 

INPUT

The input file name is WALLS.IN. The first line contains one integer: the number of regions M, 2£M£200. The second line contains one integer: the number of towns N, 3£N£250. The third line contains one integer: the number of club members L, 1£L£30, LN. The fourth line contains L distinct integers in increasing order: the labels of the towns where the members live.

After that the file contains 2M lines so that there is a pair of lines for each region: the first two of the 2M lines describe the first region, the following two the second and so on. Of the pair, the first line shows the number of towns I on the border of that region. The second line of the pair contains I integers: the labels of these I towns in some order in which they can be passed when making a trip clockwise along the border of the region, with the following exception. The last region is the “outside region” surrounding all towns and other regions, and for it the order of the labels corresponds to a trip in counterclockwise direction. The order of the regions gives an integer labeling to the regions: the first region has label 1, the second has label 2, and so on. Note that the input includes all regions formed by the towns and great walls, including the “outside region”.

OUTPUT

 

The output file name is WALLS.OUT. The first line contains one integer: the minimal crossing-sum. The second line contains one integer: the label of an optimal region. There may be several different solutions for the region and your program needs to output only one of them.

 

EXAMPLE INPUT AND OUTPUT

The following input and output files correspond to the example given in the text.

10
10
3
3 6 9
3
1 2 3
3
1 3 7
4
2 4 7 3
3
4 6 7
3
4 8 6
3
6 8 7
3
4 5 8
4
7 8 10 9
3
5 10 8
7
7 9 10 5 4 2 1

walls.in

2
3

walls.out

分析

我的做法可能略有些复杂,但非常实用,我认为是一种模板的做法。

很显然,这题的模式是我们所不熟悉的,这道题当中存在三种元素:空地、城墙、城市。而不是我们平时所熟悉的:点、路两种元素。所以,我们要做出一些改变。

首先我们先观察这三种元素,其中城市我们可以认为是一种没有什么实际意义的元素,我们做的是空地到空地,只需要最后处理一下从城市转换到空地的方式。

再接下来看,翻过城墙我们可以看作是我们平时做题的一条线段。因为城墙是我们从一个空地到另一块空地是所经过的,同时,它也收买路费,每翻越一次,就会有收“一元钱”。可以看作是权值为1的路。而空地显然相对的就成为了点。

失误

读入方式颇为奇怪,读入每个空地的周围一圈的城市,那么我们就要每两个相邻的城市连接起来来组成一条路径。建立的时候切记注意头尾的两种特殊情况啊!

最后找答案记得给各各ans变量设初值!

查错要有耐心,从有错误的地方一步步往回推,才能找到答案!

程序

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct node
 4 {
 5     int R1, R2;
 6 }Edge[300][300];
 7 int m,n,p,q[300],answer = 1000000,city[300][300],neib[300][300],dis[300][300], home[300], Count[300], ans, ans2, space[300], ansCount;
 8 int main()
 9 {
10     memset(dis, 0x3F3F3F3F, sizeof(dis));
11     freopen("walls.in","r",stdin);
12     freopen("walls.out","w",stdout);
13     cin >> m >> n >> p;
14     for (int i = 1; i <= p; i++)
15         cin >> home[i];
16     for (int i = 1; i <= m; i++)
17     {
18         dis[i][i] = 0;
19         cin >> q[i];
20         for (int j = 1; j <= q[i]; j++)
21         {
22             cin >> city[i][j];
23             neib[city[i][j]][++Count[city[i][j]]] = i;
24             if (j == 1)
25                 continue;
26             if (Edge[min(city[i][j-1],city[i][j])][max(city[i][j-1],city[i][j])].R1 == 0)
27                 Edge[min(city[i][j-1],city[i][j])][max(city[i][j-1],city[i][j])].R1 = i;
28             else
29             {
30                 Edge[min(city[i][j-1],city[i][j])][max(city[i][j-1],city[i][j])].R2 = i;
31                 dis[Edge[min(city[i][j-1],city[i][j])][max(city[i][j-1],city[i][j])].R1][i] = 1;
32                 dis[i][Edge[min(city[i][j-1],city[i][j])][max(city[i][j-1],city[i][j])].R1] = 1;
33             }
34         }
35         if (Edge[min(city[i][1],city[i][q[i]])][max(city[i][1],city[i][q[i]])].R1 == 0)
36             Edge[min(city[i][1],city[i][q[i]])][max(city[i][1],city[i][q[i]])].R1 = i;
37         else
38         {
39             Edge[min(city[i][1],city[i][q[i]])][max(city[i][1],city[i][q[i]])].R2 = i;
40             dis[Edge[min(city[i][1],city[i][q[i]])][max(city[i][1],city[i][q[i]])].R1][i] = 1;
41             dis[i][Edge[min(city[i][1],city[i][q[i]])][max(city[i][1],city[i][q[i]])].R1] = 1;
42         }
43     }
44     for (int k = 1; k <= m; k++)
45     {
46         for (int i = 1; i <= m; i++)
47         {
48             for (int j = 1; j <= m; j++)
49             {
50                 if (dis[i][j] > dis[i][k] + dis[k][j])
51                 {
52                     dis[i][j] = dis[i][k] + dis[k][j];
53                 }
54             }
55         }
56     }
57     answer = 100000000;
58     for (int i = 1; i <= m; i++)
59     {
60         ans = 0;
61         for (int j = 1; j <= p; j++)
62         {
63             ans2 = 100000000;
64             for (int k = 1; k <= Count[home[j]]; k++)
65             {
66                 ans2 = min(ans2, dis[neib[home[j]][k]][i]);
67             }
68             ans += ans2;
69         }
70         if (answer == ans)
71         {
72             space[++ansCount] = i;
73         }
74         if (answer > ans)
75         {
76             answer = ans;
77             ansCount = 0;
78             space[++ansCount] = i;
79         }
80     }
81     cout << answer << endl;
82     cout << ansCount << endl;
83     for (int i = 1; i <= ansCount; i++)
84         cout << space[i] << endl;
85     return 0;
86 }

原文地址:https://www.cnblogs.com/OIerPrime/p/9279855.html

时间: 2024-11-11 21:56:44

IOI 2000 Walls Floyd+枚举的相关文章

poj1178 floyd+枚举

http://poj.org/problem?id=1178 Description Centuries ago, King Arthur and the Knights of the Round Table used to meet every year on New Year's Day to celebrate their fellowship. In remembrance of these events, we consider a board game for one player,

USACO cowtour Floyd + 枚举

给出来的数据量还是可以的.题意:有若干个牧场,至少有两个不连通,一个牧场的直径就是牧场中最远的两个牧区的距离.要求找出几个牧场中最短的直径,就是找一条路径连接几个牧区,使这个直径最终最小. 基本方法,把整个图根据输入划分成几个不连通的牧区,然后求出每个牧区的直径(即每个连通块中的最长路径),然后枚举两个不在同一牧区的点,设blocks[i]记录第i个节点所在连通块的直径,那么result = min(blocks[i] + dis(i, j) + blocks[j]),可以用并查级判断两个点是否

【基础练习】【floyd+枚举】codevs1020 孪生蜘蛛题解

题目描述 Description 在G城保卫战中,超级孪生蜘蛛Phantom001和Phantom002作为第三层防卫被派往守护内城南端一带极为隐秘的通道. 根据防护中心的消息,敌方已经有一只特种飞蛾避过第二层防卫,直逼内城南端通道入口.但优秀的蜘蛛已经在每个通道内埋下了坚固的大网,无论飞蛾进入哪个通道,他只有死路一条!(因为他是无法挣脱超级蛛网的) 现在,001和002分别驻扎在某两个通道内.各通道通过内线相通,通过每条内线需要一定的时间.当特种飞蛾被困某处,001或002会迅速赶来把它结果掉

Stockbroker Grapevine (poj 1125 floyd + 枚举)

Language: Default Stockbroker Grapevine Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 27445   Accepted: 15211 Description Stockbrokers are known to overreact to rumours. You have been contracted to develop a method of spreading disinfo

poj 1161 Floyd+枚举

题意是: 给出n个点,围成m个区域.从区域到另一个区域间需穿过至少一条边(若两区域相邻)——边连接着两点. 给出这么一幅图,并给出一些点,问从这些点到同一个区域的穿过边数最小值. 解题思路如下: 将区域按1~m编号,d[i][j]表示第 i 个区域到第 j 个区域的最短距离,跑一遍Floye算法O(m^3)后,枚举选择的区域,找出其中穿过边数最小值即可. 建图:题目对于每个区域的描述方式为以顺时针方向给出围成区域的点.由此可知区域由哪些边组成.易知,每条边能且只能令两个区域相邻,则用二维数组记录

POJ 1161 Walls ( Floyd &amp;&amp; 建图 )

题意 :  在某国,城市之间建起了长城,每一条长城连接两座城市.每条长城互不相交.因此,从一个区域到另一个区域,需要经过一些城镇或者穿过一些长城.任意两个城市A和B之间最多只有一条长城,一端在A城市,另一端在B城市.从A走到B,可以只在一个区域内行走,或者只在长城上行走. 有一个俱乐部,它的会员分布在不同的城市中,每个城市要么只有一个会员,要么没有会员.会员们决定要集中到一个区域内聚会.他们骑车前往目的地.首先,由于城市内交通太堵,他们不想进入任何一个城市内,其次,他们希望穿越尽可能少的长城.他

枚举(enumeration)

C++的enum工具提供了另一种创建符号常量的方式,这种方式可以代替const.它还允许定义新类型,但必须按严格的限制进行.使用enum的句法与使用结构相似. enum spectrum{red,orange,yellow,green,blue,violet,indigo,ultraviolet}; 这条语句完成两项工作. 让spectrum成为新类型的名称:spectrum被称为枚举,就像struct变量被称为结构一样. 将red.orange.yellow等作为符号常量它们对应整数值0~7.

[bzoj2208][Jsoi2010]连通数

来自FallDream的博客,未经允许,请勿转载,谢谢. n<=2000 bitset优化floyd , 枚举k,枚举i,如果i能到k,那么i的bitset直接或上k的.复杂度$O(\frac{n^{3}}{32})$ #include<iostream> #include<cstdio> #include<bitset> #define MN 2000 using namespace std; inline int read() { int x = 0 , f

图论常用算法之一 POJ图论题集【转载】

POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:http://poj.org/ 1062* 昂贵的聘礼 枚举等级限制+dijkstra 1087* A Plug for UNIX 2分匹配 1094 Sorting It All Out floyd 或 拓扑 1112* Team Them Up! 2分图染色+DP 1125 Stockbroker