poj1861 network(并查集+kruskal最小生成树

题目地址:http://poj.org/problem?id=1861

 

题意:输入点数n和边数n,m组边(点a,点b,a到b的权值)。要求单条边权值的最大值最小,其他无所谓(所以多解:(。输出单条边最大值,边的数量,每条边(点a,点b)。

 

思路:结构体记录节点x,y和权值d。写一个比较函数+sort使结构体按权值由小到大排序。

并查集:两个集合被选中的和没被选中的。

kruskal:初始化每个节点独自一个集合,每次输入不在一个集合的就合并并记录,在一个集合的不管。输出记录数组最后一个节点的权值(edge[c-1].d),记录数组大小(c-1),每条边(从1到c-1)【kruskal函数最后一次多了一个c++,脚标又是从1开始。

 1 #include <cstdio>
 2 #include <algorithm>
 3 
 4 using namespace std;
 5 
 6 const int N = 15000+5;
 7 
 8 struct bian
 9 {
10     int x, y, d;
11 }edge[N], ans[N];
12 
13 int fa[N], c = 1, n, m;
14 
15 int cmp(bian a, bian b)
16 {
17     return a.d < b.d;
18 }
19 
20 void init(int n)
21 {
22     for(int i = 1; i <= n; i++)
23         fa[i] = i;
24 }
25 
26 int found(int x)
27 {
28     if(fa[x] == x)
29         return x;
30     else
31         fa[x] = found(fa[x]);
32     return fa[x];
33 }
34 
35 void unite(int x, int y)
36 {
37     int px = found(x);
38     int py = found(y);
39     if(px == py)
40         return;
41     fa[py] = px;
42 }
43 
44 void kruskal()
45 {
46     for(int i = 1; i <= m; i++)
47     {
48         int x = edge[i].x;
49         int y = edge[i].y;
50         if(found(x) != found(y))//两顶点不在一个集合则把该边放入
51         {
52             unite(x, y);
53             ans[c].x = x;
54             ans[c].y = y;
55             ans[c].d = edge[i].d;
56             c++;
57         }
58     }
59 }
60 
61 int main()
62 {
63     scanf("%d%d", &n, &m);//n个点,m条边
64     init(n);
65     for(int i = 1; i <= m; i++)
66     {
67         scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].d);
68     }
69     sort(edge+1, edge+m+1, cmp);//sort函数是从0到n-1的!!!!!!!!!!!!!!!
70     kruskal();
71     printf("%d\n", ans[c-1].d);
72     printf("%d\n", c-1);
73     for(int i = 1; i < c; i++)
74     {
75         printf("%d %d\n", ans[i].x, ans[i].y);
76     }
77     return 0;
78 }

 

【玛德!!!!!!!!!!!sort默认从0到n-1!!!!!!!!!!要是脚标从1开始记得改成sort(a+1, a+n+1)!!!!!!!!!!!】

posted @ 2015-08-20 14:50  _正版索粒  阅读(561)  评论(0编辑  收藏  举报