poj1251 Jungle Roads(Prime || Kruskal)

题目链接

http://poj.org/problem?id=1251

题意

有n个村庄,村庄之间有道路连接,求一条最短的路径能够连接起所有村庄,输出这条最短路径的长度。

思路

最小生成树问题,使用普利姆算法(Prime)或者克鲁斯卡尔算法(Kruskal)解决。

代码

Prime算法:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 
 7 const int INF = 0xfffffff;
 8 const int N = 30;
 9 int n;
10 int jungle[N][N];
11 int dist[N];    //记录从起点到其余各点的距离并不断更新
12 
13 int prime()
14 {
15     int min_edge, min_node;
16     for (int i = 0; i < n; i++)
17         dist[i] = INF;
18     int now = 0;
19     int ans = 0;
20     for (int i = 0; i < n - 1; i++)
21     {
22         dist[now] = -1;    //标记结点now+'A'被访问过了
23         min_edge = INF;
24         for (int j = 0; j < n; j++)
25         {
26             if (j != now && dist[j]>=0)
27             {
28                 if (jungle[now][j]>0)
29                     dist[j] = min(dist[j], jungle[now][j]);
30                 if (dist[j] < min_edge)
31                 {
32                     min_edge = dist[j];    //选取从当前结点到其余各点的最短路径
33                     min_node = j;
34                 }
35             }
36         }
37         now = min_node;
38         ans += min_edge;    //当前最小生成树的长度
39     }
40     return ans;
41 }
42 
43 int main()
44 {
45     //freopen("poj1251.txt", "r", stdin);
46     while (cin >> n && n)
47     {
48         memset(jungle, 0, sizeof(jungle));
49         for (int i = 0;i < n-1;i++)
50         {
51             char p, q;
52             int v, w;
53             cin >> p >> v;
54             for (int j = 0;j < v;j++)
55             {
56                 cin >> q >> w;
57                 jungle[p - 'A'][q - 'A'] = w;
58                 jungle[q - 'A'][p - 'A'] = w;
59             }
60         }
61         int ans = prime();
62         cout << ans << endl;
63     }
64     return 0;
65 }

Kruskal算法:

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 
 7 const int N = 100;
 8 int s[N], e[N], v[N];    //分别存储每一条路的起点、终点、长度
 9 int p[N];    //并查集使用
10 int n;
11 int cnt;    //存储有多少条路
12 
13 bool cmp(int i, int j)
14 {
15     return v[i] < v[j];
16 }
17 
18 int find_root(int x)
19 {
20     if (p[x] == -1)
21         return x;
22     else return find_root(p[x]);
23 }
24 
25 int kruskal()
26 {
27     memset(p, -1, sizeof(p));
28     int r[N];
29     for (int i = 0; i < cnt; i++)
30         r[i] = i;
31     sort(r, r + cnt, cmp);    //根据路径长度v[]的大小对数组r[]排序
32     int ans = 0;
33     for (int i = 0; i < cnt; i++)
34     {
35         int cur = r[i];
36         int a = find_root(s[cur]);
37         int b = find_root(e[cur]);
38         if (a != b)
39         {
40             ans += v[cur];
41             p[a] = b;
42         }
43     }
44     return ans;
45 }
46 
47 int main()
48 {
49     //freopen("poj1251.txt", "r", stdin);
50     while (cin >> n && n)
51     {
52         cnt = 0;
53         char p, q;
54         int nums, w;
55         for (int i = 0; i < n - 1; i++)
56         {
57             cin >> p >> nums;
58             for (int j = 0; j < nums; j++)
59             {
60                 cin >> q >> w;
61                 s[cnt] = p - 'A';
62                 e[cnt] = q - 'A';
63                 v[cnt] = w;
64                 cnt++;
65             }
66         }
67         int ans = kruskal();
68         cout << ans << endl;
69     }
70     return 0;
71 }

 

posted @ 2017-12-03 11:23  ColdCode  阅读(218)  评论(0编辑  收藏  举报
AmazingCounters.com