hdu3367并查集
来源:互联网 发布:办公软件基本知识 编辑:程序博客网 时间:2024/05/13 06:35
#include<stdio.h>#include<stdlib.h>#include<iostream>#include<string.h>using namespace std;#define N 1000int f[N],vis[N];struct node{ int a ,b,w; friend bool operator <(const node &A,const node &B) {return A.w>B.w;}};node data[N];int find(int a){ int i=a; while(f[i]!=i) i=f[i]; int j=a,k; while(f[j]!=i) { k=f[j]; f[j]=i; j=k; } return i;}void union1(int a ,int b){ int fa=f[a]; int fb=f[b]; if(fa!=fb) f[fa]=fb;}void init(int n){for(int i=1;i<=n;i++) f[i]=i;}int main(){ int i,j,n,m,ans; while(scanf("%d%d",&n,&m)) { if(!n&&!m)break; ans=0; memset(vis,0,sizeof(vis)); init(n); for(i=1;i<=m;i++) scanf("%d%d%d",&data[i].a,&data[i].b,&data[i].w); sort(data+1,data+1+m); for(i=1;i<=m;i++) { int a=find(data[i].a); int b=find(data[i].b); if(a!=b)//一开始肯定都是不在一颗树上的,连起来 { if(vis[a]&&vis[b])continue; if(vis[a]||vis[b])vis[a]=vis[b]=1; union1(a,b);//无论怎样都连起来 ans+=data[i].w; } else if(!vis[a])//在同一棵树上却都没有环,才可以将两点连起来 { vis[a]=vis[b]=1; union1(a,b); ans+=data[i].w; }//这里不用else,就是如果有环,丢掉 } printf("%d\n",ans); } return 0;}/*3 30 1 11 2 12 0 14 50 1 11 2 12 3 13 0 10 2 20 0*/这道题的做法和克鲁斯卡尔算法过程上差不多,都是利用了并查集的性质合并的时候分三种情况:1是否两个都有环,2其中一个有环,3两个都没有环有位朋友说:不能直接求最大生成树,有待验证!判断树有没有环,用Vis数组,这个过程很典型!