POJ - 1287超级模板题
大概意思就是点的编号从1到N,会给你m条边,可能两个点之间有多条边这种情况,求最小生成树总长度?
这题就不解释了,总结就算,prim是类似dijkstra,从第一个点出发,每次走这个点没走过的最小边权值,这样不断找下去就可以找出,本质就是贪心算法
而kruskal是利用并查集,先按照边权值大小排序,然后从小的边开始往里面添加边,利用并查集判断是否在一个联通分量里面(就是是否相连)如果不相
连就建立边,从而建图,注意,节点编号如果是从1->n,那么相应初始化就应该从1->N;
prim版本:
1 #include<iostream> 2 #include<stdio.h> 3 #include<string.h> 4 using namespace std; 5 const int INF = 0x3f3f3f3f; 6 const int maxx = 1e2+7; 7 int cost[maxx][maxx]; 8 int mincost[maxx]; 9 bool used[maxx]; 10 int v; 11 int m,n; 12 int prim(){ 13 for (int i=1;i<=n;i++){ 14 mincost[i]=INF; 15 used[i]=false; 16 } 17 mincost[1]=0;//这里的数组的编号,代表我最开始建图的点 18 int res=0; 19 while(true){ 20 int v = -1; 21 for (int u=1;u<=n;u++){ //枚举边找到这个点的下一个边权值最小的点 22 if (!used[u] && (v==-1 || mincost[u] < mincost[v])) v=u; 23 } 24 if (v == -1)break;//没有的话就返回,无法建图 25 used[v]=true;//顶点加入 26 res+=mincost[v]; 27 for (int u=1;u<=n;u++){ 28 mincost[u] = min(mincost[u],cost[v][u]);//??? 29 } 30 } 31 return res; 32 } 33 int main(){ 34 int tmp1,tmp2,tmp3; 35 while(scanf("%d",&n) && n){ 36 scanf("%d",&m); 37 if (m==0){ 38 cout<<"0"<<endl; 39 continue; 40 } 41 for (int i=1;i<=n;i++){ 42 for(int j=1;j<=n;j++){ 43 if (i==j)cost[i][j]=0; 44 else cost[i][j]=INF; 45 } 46 } 47 for (int i=1;i<=m;i++){ 48 scanf("%d%d%d",&tmp1,&tmp2,&tmp3); 49 if (tmp3<cost[tmp1][tmp2])cost[tmp1][tmp2]=cost[tmp2][tmp1]=tmp3;//更新成最短边 50 } 51 cout<<prim()<<endl; 52 } 53 return 0; 54 }
Kruskal
#include<iostream> #include<string.h> #include<stdio.h> #include<algorithm> using namespace std; struct node{ int u,v,w; }a[10050]; int p[10055]; int r[10055]; int n,m; int find(int x){return p[x] == x ? x : p[x] = find(p[x]);}//找根节点 int cmp(node x,node y) { return x.w<y.w;//按照边权值排序 } int Kruskal(){ int ans=0; int num=0; for (int i=1; i<=n; i++)p[i]=i; sort(a+1,a+1+m,cmp); for (int i=1; i<=m; i++) { int x=find(a[i].u);//出发点的根节点 int y=find(a[i].v);//到达点的根节点 if (x!=y)//不是一个根节点 { ans+=a[i].w;//连接 p[x]=y;//y是x的父亲节点 num++;//建立好了n-1条边 } if (num==n-1){ break; } } return ans; } int main() { int tmp1,tmp2,tmp3; while(~scanf("%d",&n)) { if (n==0)break; scanf("%d",&m); for (int i=1; i<=m; i++) { scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w); } printf("%d\n",Kruskal()); } return 0; }