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)!!!!!!!!!!!】