最小生成树水题……全部用kruskal模板编写。(结合并查集)
POJ2377
注意kruskal的各个步骤
注意使用时对模板的修改
/*kruskal **并查集实现 **1.边权值排序sort **2.选择最小的边 **3.判断最小边上的点是否同一集合 **不是同一集合就合并 */ #include <cstdio> #include <vector> #include <algorithm> using namespace std; #define MAX 1002 struct edge{ int u,v,cost; }; vector<edge> G; int V,E; int rank[MAX],par[MAX]; void init(int n){ for(int i=0;i<n;i++){ rank[i]=0; par[i]=i; } return ; } int find(int x){ if(par[x]==x) return x; else return par[x]=find(par[x]); } bool same(int x,int y){ return find(x)==find(y); } void unit(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]){ par[x]=y; }else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool mycom(const edge &e1,const edge &e2){ return e1.cost>e2.cost; } int main(){ scanf("%d%d",&V,&E); init(V); edge ed; for(int i=0;i<E;i++){ scanf("%d %d %d",&ed.u,&ed.v,&ed.cost); G.push_back(ed); } sort(G.begin(),G.end(),mycom); int res=0; int temp=1; for(int i=0;i<E;i++){ if(!same( G[i].u, G[i].v ) ){ unit(G[i].u,G[i].v); res+=G[i].cost; temp++; } } if(temp!=V){ puts("-1"); }else printf("%d\n",res); return 0; }
POJ1258
处理输入格式,由于是无向图,只需要获得上三角或者下三角的数据即可
然后存进来,用kruskal
不过这道题边比较多,感觉更适合用prim,但是kruskal也能做的嘛~
他俩时间复杂度都是o(E logV)
/*kruskal **并查集实现 **1.边权值排序sort **2.选择最小的边 **3.判断最小边上的点是否同一集合 **不是同一集合就合并 */ #include <cstdio> #include <vector> #include <algorithm> using namespace std; #define MAX 110 struct edge{ int u,v,cost; }G[5000]; edge ed; int V,E; int rank[MAX],par[MAX]; void init(int n){ for(int i=0;i<n;i++){ rank[i]=0; par[i]=i; } return ; } int find(int x){ if(par[x]==x) return x; else return par[x]=find(par[x]); } bool same(int x,int y){ return find(x)==find(y); } void unit(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]){ par[x]=y; }else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool mycom(const edge &e1,const edge &e2){ return e1.cost<e2.cost; } int main(){ int n; while(scanf("%d",&n)!=EOF){ int t,k=0; for(int i=0;i<n;i++){a for(int j=0;j<n;j++){ scanf("%d",&t); if(i<j){ ed.u=i,ed.v=j,ed.cost=t; G[k++]=ed; } } } init(n); sort(G,G+k,mycom); int res=0; for(int i=0;i<k;i++){ if(!same( G[i].u, G[i].v ) ){ unit(G[i].u,G[i].v); res+=G[i].cost; } } printf("%d\n",res); } return 0; }
poj2358
根据题意实际上就是求最小生成树中的最长边。
kruskal是先排序然后依次加入边,(前提是这个边不会构成环),所以每次都是保存最小生成树中最后加入的边
所以最后插入的边就是答案。
#include <cstdio> #include <vector> #include <algorithm> using namespace std; #define MAX 2002 struct edge{ int u,v,cost; }; vector<edge> G; int V,E; int rank[MAX],par[MAX]; void init(int n){ for(int i=0;i<n;i++){ rank[i]=0; par[i]=i; } return ; } int find(int x){ if(par[x]==x) return x; else return par[x]=find(par[x]); } bool same(int x,int y){ return find(x)==find(y); } void unit(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]){ par[x]=y; }else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool mycom(const edge &e1,const edge &e2){ return e1.cost<e2.cost; } int main(){ scanf("%d%d",&V,&E); init(V); edge ed; for(int i=0;i<E;i++){ scanf("%d %d %d",&ed.u,&ed.v,&ed.cost); G.push_back(ed); } sort(G.begin(),G.end(),mycom); int res=G[0].cost; int temp=1; for(int i=0;i<E;i++){ if(!same( G[i].u, G[i].v ) ){ unit(G[i].u,G[i].v); res=G[i].cost; } } printf("%d\n",res); return 0; }
hdu1233
畅通工程
#include <cstdio> #include <vector> #include <algorithm> using namespace std; #define MAX 102 struct edge{ int u,v,cost; }; vector<edge> G; int ran[MAX],par[MAX]; int V,E; /*并查集*/ void init(int n){ for(int i=0;i<=n;i++){ ran[i]=0; par[i]=i; } } int find(int x){ if(x==par[x]) return x; else return par[x]=find(par[x]); } bool same(int x,int y){ return find(x)==find(y); } void unit(int x,int y){ x=find(x),y=find(y); if(x==y) return ; if(ran[x]<ran[y]){ par[x]=y; } else{ par[y]=x; if(ran[x]==ran[y]) ran[x]++; } } bool mycom(const edge &e1,const edge &e2){ return e1.cost<e2.cost; } int main(){ edge ed; while(scanf("%d",&V)!=EOF&&V!=0){ G.clear(); E=V*(V-1)/2; for(int i=0; i<E; i++){ scanf("%d%d%d",&ed.u,&ed.v,&ed.cost); G.push_back(ed); } sort(G.begin(),G.end(),mycom); init(V); int res=0; for(int i=0;i<G.size();i++){ if(!same(G[i].u,G[i].v)){ unit(G[i].u,G[i].v); res+=G[i].cost; } } printf("%d\n",res); } return 0; }