POJ 1161 Walls【floyd 以面为点建图】

题目链接:http://poj.org/problem?id=1161

题目大意:

1.给出m个区域,n个俱乐部点。接下来是n个俱乐部点以及各个区域由什么点围成。求一个区域到各个俱乐部点的距离之和最小。

解题思路:

1.这题建图比较麻烦,以区域为点建图,区域之间若有边,则两区域的距离为1,建完图后跑一遍floyd就可以求出两两区域的最小距离。

2.对于答案,枚举每一个区域到各个俱乐部点的相邻区域的距离之和,取最小值。

POJ 1161 Walls【floyd 以面为点建图】
 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define mem(a, b) memset(a, b, sizeof(a))
 5 using namespace std;
 6 const int inf = 0x3f3f3f3f;
 7 
 8 int m, n, l;
 9 int club[35], vis[260][210];//标记i点是否与j区域相邻 
10 int edge[260][260]; //更新i到j边的相邻区域是哪个
11 int map[260][260]; //建图 
12 
13 void floyd()
14 {
15     for(int i = 1; i <= m; i ++)
16         map[i][i] = 0;
17     for(int k = 1; k <= m; k ++)
18         for(int i = 1; i <= m; i ++)
19             for(int j = 1; j <= m; j ++)
20                 map[i][j] = map[j][i] = min(map[i][j], map[i][k] + map[k][j]);
21 }
22 
23 int main()
24 {
25     while(scanf("%d", &m) != EOF) //m个区域 
26     {
27         mem(edge, -1); //表示没有相邻区域 
28         mem(map, inf), mem(vis, -1);
29         scanf("%d%d", &n, &l);//n个点,其中l个点是俱乐部所在的点 
30         for(int i = 1; i <= l; i ++)
31             scanf("%d", &club[i]);
32         for(int i = 1; i <= m; i ++)
33         {
34             int k, temp;
35             scanf("%d", &k); //每个区域由k个点逆时针围成 注意最后一个点与第一个点也有边 
36             scanf("%d", &temp);
37             vis[temp][i] = 1;
38             int first = temp;
39             for(int j = 1; j < k; j ++)
40             {
41                 int x;
42                 scanf("%d", &x);
43                 vis[x][i] = 1;
44                 if(edge[temp][x] == -1 || edge[x][temp] == -1)
45                     edge[temp][x] = edge[x][temp] = i;
46                 else
47                 {
48                     map[edge[temp][x]][i] = map[i][edge[temp][x]] = 1;
49                     edge[temp][x] = edge[x][temp] = i;
50                 }
51                 temp = x;
52             }
53             if(edge[first][temp] == -1 || edge[temp][first] == -1)
54                 edge[first][temp] = edge[temp][first] = i;
55             else
56             {
57                 map[edge[first][temp]][i] = map[i][edge[first][temp]] = 1;
58                 edge[first][temp] = edge[temp][first] = i;
59             }
60         }
61         floyd();
62         int ans = inf;
63         for(int i = 1; i <= m; i ++) //枚举答案 枚举每一个区域 
64         {
65             int temp = 0;
66             for(int j = 1; j <= l; j ++)
67             {
68                 int temp1 = inf;
69                 for(int k = 1; k <= m; k ++)
70                 {
71                     if(vis[club[j]][k] == -1)
72                         continue;
73                     temp1 = min(temp1, map[i][k]);
74                 }
75                 temp += temp1;
76             }
77             ans = min(ans, temp);
78         }
79         printf("%d\n", ans);
80     }
81     return 0;
82 }
View Code

 

上一篇:算法——最短路径 Dijkstra算法和Floyd算法


下一篇:图论——Floyd算法拓展及其动规本质