首页 > 代码库 > POJ 3522 Slim Span (并查集 + 枚举 + kruskal)
POJ 3522 Slim Span (并查集 + 枚举 + kruskal)
链接:点击打开链接
题目好长, 而且还有图片,所以就不复制粘贴过来了,这道题的大意是:
一棵树T(连通无环子图)将用n-1条边连接原图的所有的n个顶点,生成的生成树的最大权值边与最小权值边的差(称“苗条值”)尽量小,找出这个最小的苗条值;
思路:
用kruskal枚举;
首先对每条边的权值从小到大进行排序;
枚举每条边为最小边生成最小生成树,并计算这样的生成树的苗条值,枚举玩所有的情况就可以求出苗条值;
代码解析如下:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <stack> #include <queue> #include <map> #include <set> #include <cmath> #include <algorithm> #define MAXN 1000005 #define RST(N)memset(N, 0, sizeof(N)) using namespace std; typedef struct Edge_ { int x, y; int rank; }Edge; Edge edge[MAXN]; int n, m, res, Kc, father[MAXN]; int cmp(const void *a, const void *b) { Edge *p1 = (Edge *)a; Edge *p2 = (Edge *)b; return p1->rank - p2->rank; } int find(int x) //路径压缩寻找父节点 { return x == father[x] ? x : find(father[x]); } int solve(int x) { int cnt = 0; for(int i=1; i<=n; i++) father[i]=i; for(int i=x; i<m; i++) { //kruskal试生成最小生成树; int fx = find(edge[i].x); int fy = find(edge[i].y); if(fx != fy) { father[fx] = fy; cnt++; } if(cnt == n-1) return edge[i].rank-edge[x].rank; } return MAXN; } int main() { while(~scanf("%d %d", &n, &m) && n || m) { res = MAXN; for(int i=0; i<m; i++) { scanf("%d %d %d", &edge[i].x, &edge[i].y, &edge[i].rank); } qsort(edge, m, sizeof(Edge), cmp); //权值从大到小; for(int i=0; i<=m-n+1; i++) { //从0 ~ m-(n-1)的范围枚举 res = solve(i) < res ? solve(i) : res; //寻找最小差值; } if(res == MAXN) res = -1; //不存在的话 printf("%d\n", res); } return 0; }
POJ 3522 Slim Span (并查集 + 枚举 + kruskal)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。