标签:
题目连接:http://poj.org/problem?id=1861
题目的意思就是找最小生成树
那我们选择kruskal算法 我先来说一下kruskal算法:假设 WN=(V,{E}) 是一个含有 n 个顶点的连通网,则按照克鲁斯卡尔算法构造最小生成树的过程为:先构造一个只含 n 个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树上的根结点,则它是一个含有 n 棵树的一个森林。之后,从网的边集 E 中选取一条权值最小的边,若该条边的两个顶点分属不同的树,则将其加入子图,也就是说,将这两个顶点分别所在的两棵树合成一棵树;反之,若该条边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。依次类推,直至森林中只有一棵树,也即子图中含有 n-1条边为止。
下面看代码:
#include<stdio.h> #include<math.h> #include<string.h> #include<algorithm> #include<iostream> using namespace std; #define MAX 15001 int bin[1002]; struct node { int x,y; int w; }edge[MAX],v[MAX];//v用来存用的边 以便输出 int rank[MAX]; //rank[x]代表x的孩子有多少个 int findx(int x) //找父亲节点的函数 { if(x != bin[x]) { bin[x] = findx(bin[x]); } return bin[x]; /*int r = x; while(r != bin[r]) { r = bin[r]; } return r;*/ } int cmp(node e1,node e2) { return e1.w < e2.w; } void Union(int x,int y) { if(x == y)return; if(rank[x] > rank[y]) { bin[y] = x; } else { if(rank[x] == rank[y]) { rank[y]++; } bin[x] = y; } } int main() { int i,j,n,m,k,max; scanf("%d%d",&m,&n); for(i = 0;i < n;i++) { scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].w); //printf("%d %d %d*\n",edge[i].x,edge[i].y,edge[i].w); } for(i = 0;i < m;i++) { bin[i] = i; //记录父亲节点 rank[i] = 0; //记录儿子节点的个数 为了更新根节点用 } sort(edge,edge + n,cmp); k = 0; max = 0; int a,b; for(i = 0;i < n;i++) { a = findx(edge[i].x); b = findx(edge[i].y); if(a != b) { k++; //printf("%d %d*\n",edge[i].x,edge[i].y); Union(a,b); v[k] = edge[i]; if(edge[i].w > max) { max = edge[i].w; } } } printf("%d\n",max); printf("%d\n",k); for(i = 1;i <= k;i++) { printf("%d %d\n",v[i].x,v[i].y); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zhanyage110/p/4394856.html