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, L£N. 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
2 3
分析
我的做法可能略有些复杂,但非常实用,我认为是一种模板的做法。
很显然,这题的模式是我们所不熟悉的,这道题当中存在三种元素:空地、城墙、城市。而不是我们平时所熟悉的:点、路两种元素。所以,我们要做出一些改变。
首先我们先观察这三种元素,其中城市我们可以认为是一种没有什么实际意义的元素,我们做的是空地到空地,只需要最后处理一下从城市转换到空地的方式。
再接下来看,翻过城墙我们可以看作是我们平时做题的一条线段。因为城墙是我们从一个空地到另一块空地是所经过的,同时,它也收买路费,每翻越一次,就会有收“一元钱”。可以看作是权值为1的路。而空地显然相对的就成为了点。
失误
读入方式颇为奇怪,读入每个空地的周围一圈的城市,那么我们就要每两个相邻的城市连接起来来组成一条路径。建立的时候切记注意头尾的两种特殊情况啊!
最后找答案记得给各各ans变量设初值!
查错要有耐心,从有错误的地方一步步往回推,才能找到答案!
程序
1 #include2 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 }