您的位置:首页 > 其它

POJ1161 Walls(Floyd+建图)

2014-04-05 00:05 363 查看
题目链接:http://poj.org/problem?id=1161

Walls

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 7386 Accepted: 3617
Description

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 the optimal region(s) and the minimal crossing-sum. 

Input

Your program is to read from standard input. 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 input 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

Your program is to write to standard output. The first line contains one integer: the minimal crossing-sum.
Sample Input
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

Sample Output
2


题意:一个地方,有用墙分成的m个区域,和n个城镇。现在有一个俱乐部,一个城镇中最多有一个成员。现在他们要聚会,问去哪个区域才能让所有成员穿过城墙的次数之和最少?

输入数据:

第一行为m,表示有m个区域。

第二行为n,表示有n个城镇。

接下来为l,表示俱乐部人数。

然后l个数,表示每个人分别在哪个城镇。

然后m组,每组描述一个区域。(包括最外面的区域)

第一行表示围成区域的点数,第二行逆时针顺序表示这几个点。

题目意思很明确,要求出穿墙次数最少,其实就是最短路。但这张图明显不是我们需要用到的图,所以要把它转化成以区域为点,墙为边的图,这也是这道题最麻烦的地方。

建图时顺便求出与俱乐部成员所在城镇相邻的区域。

转化完之后,先用Floyd求出多源最短路,然后对于每一个与俱乐部成员所在城镇相邻的区域,都求出到每个区域的最短路之和,在其中找出最短的数,即为所要求的答案。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
using namespace std;
#define INF 0x3f3f3f3f

int g[255][255];//建的图(区域为点)
int m,n,l;
int club[255];//俱乐部成员所在的城镇
int marke[255][255];//表示i和j之间的边相邻的区域
int adj[255][255];//表示j是否与城镇i相邻

int main()
{
while (scanf("%d",&m)!=EOF)
{
memset(g,0x3f,sizeof(g));
scanf("%d",&n);
scanf("%d",&l);
for (int i=1;i<=l;i++)
{
scanf("%d",&club[i]);
}
memset(marke,-1,sizeof(marke));
memset(adj,0,sizeof(adj));
for (int i=1;i<=m;i++)
{
int x,tmp1,tmp2,tmp;
scanf("%d",&x);
scanf("%d",&tmp1);
adj[tmp1][i]=1;//标记i与点tmp相邻
tmp=tmp1;
for (int j=1;j<x;j++)
{
scanf("%d",&tmp2);
adj[tmp2][i]=1;
if (marke[tmp1][tmp2]==-1) {marke[tmp1][tmp2]=i;marke[tmp2][tmp1]=i;}//如果tmp1,tmp2没有相邻区域,则标为与i相邻
else {g[marke[tmp1][tmp2]][i]=1;g[i][marke[tmp1][tmp2]]=1;marke[tmp2][tmp1]=i;}//如果有,则说明之前的区域与i区域相邻,建图
tmp1=tmp2;
}
if (marke[tmp][tmp2]==-1) {marke[tmp][tmp2]=i;marke[tmp2][tmp]=i;}//注意首尾也是一条边
else {g[marke[tmp][tmp2]][i]=1;g[i][marke[tmp][tmp2]]=1;marke[tmp2][tmp]=i;}
}
for (int i=1;i<=n;i++) g[i][i]=0;//开始Floyd算法
for (int k=1;k<=m;k++)
{
for (int i=1;i<=m;i++)
{
for (int j=1;j<=m;j++)
{
if (g[i][j]>g[i][k]+g[k][j]) g[i][j]=g[i][k]+g[k][j];
}
}
}
int ans=INF;
for (int i=1;i<=m;i++)
{
int sum=0;
for (int j=1;j<=l;j++)//俱乐部情况
{
int mi=INF;
for (int k=1;k<=m;k++)//找出从与俱乐部成员所在城镇相邻的哪个区域出发最少
{
if (adj[club[j]][k]==0) continue;//如果与俱乐部成员所在城镇不相邻则无视
if (g[k][i]<mi) mi=g[k][i];//找出到区域i的最小值
}
sum+=mi;//俱乐部次数之和
}
if (sum<ans) ans=sum;//总的最少情况
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj Floyd