poj1161 Walls

 1 #include<cstdio>
 2 #include<iostream>
 3 #define MAX 0xfffffff
 4 using namespace std;
 5 int m,l;
 6 int Area[201][251],G[201][201],People[251],Dist[31];
 7 int Init()//初始化数据 
 8 {
 9     int i,j,k,t;
10     for(i=1;i<=l;++i)
11     {
12         scanf("%d",&t);
13         People[t]=i;
14     }
15     for(i=1;i<=m;++i)
16         for(j=1;j<=m;++j)
17             if(i!=j)
18             G[i][j]=MAX;
19     for(i=1;i<=m;++i)
20     {
21         scanf("%d",&Area[i][0]);
22         for(j=1;j<=Area[i][0];++j)
23             scanf("%d",&Area[i][j]);
24         Area[i][j]=Area[i][1];//记得区域是封闭的,所以加了这点 
25         for(j=1;j<=Area[i][0];++j)
26             for(k=1;k<i;++k)
27                 for(t=1;t<=Area[k][0];++t)
28                     if(Area[i][j]==Area[k][t+1]&&Area[i][j+1]==Area[k][t])//判断两块区域是否相邻 
29                     G[i][k]=G[k][i]=1;
30     }
31 }
32 int Solve()
33 {
34     int i,j,k,t,sum=MAX;
35     for(k=1;k<=m;++k)//Floyd求所有点之间的最短路径,也即是需要翻越的墙数 
36         for(i=1;i<=m;++i)
37             for(j=1;j<=m;++j)
38                 G[i][j]=min(G[i][j],G[i][k]+G[k][j]);
39     for(k=1;k<=m;++k)//枚举以每一块区域作为聚集块 
40     {
41         for(i=1;i<=l;++i)
42             Dist[i]=MAX;
43         for(i=1;i<=m;++i)
44             for(j=1;j<=Area[i][0];++j)
45             if(People[Area[i][j]]>0&&Dist[People[Area[i][j]]]>G[k][i])//每个人到第k块的最短路径 
46                 Dist[People[Area[i][j]]]=G[k][i];
47         for(t=0,i=1;i<=l;++i)//求总和 
48             t+=Dist[i];
49         if(sum>t) sum=t;//更新sum 
50     }
51     return sum;
52 }
53 int main()
54 {
55     while(~scanf("%d%*d%d",&m,&l)){//n没有用,直接跳过 
56         Init();
57         printf("%d\n",Solve());
58     }
59     return 0;
60 }

题意很简单,很容易理解,但是题目只告诉了我们一个地区是由几个顶点组成的这个条件,并没有告诉我们一个地区到另一个地区需要经过几道墙。所以问题的重点就是将已知的图转化成我们所需要的图。

因为题中一块区域周围的点都是按顺时针给出的,所以要判断两个区域是否相邻的时候,首先找到区域A中的某个点a1,如果区域B的周围也有a1,此时,比较A区域中a1的后继与B区域中a1的前继或者A区域中a1的前继与B区域中a1的后继是否相同,如果相同,两个区域便是相邻的。即在邻接表中,A到B的权值是1。

老师留的是并查集的作业,貌似本题用不上并查集!!!

posted on 2012-08-14 19:38  小花熊  阅读(303)  评论(0编辑  收藏  举报

导航