51Nod 1212无向图最小生成树
prim
#include<stdio.h> #include<string.h> #define inf 0x3f3f3f3f int G[1001][1001]; int vis[1001],lowc[1001]; int prim(int G[][1001],int n){ int i,j,p,minc,res=0; memset(vis,0,sizeof(vis));//全部初值为0表示没有访问过; vis[1]=1; for(i=2;i<=n;i++) lowc[i]=G[1][i]; for(i=2;i<=n;i++){ minc=inf; p=-1; for(j=1;j<=n;j++){ if(vis[j]==0&&lowc[j]<minc) {minc=lowc[j];p=j;} } if(inf==minc) return -1;//原图不连通 res+=minc; vis[p]=1; for(j=1;j<=n;j++){//更新lowc[] if(vis[j]==0&&lowc[j]>G[p][j]) lowc[j]=G[p][j]; } } return res; } int main(){ int n,m; int x,y,w; while(~scanf("%d %d",&n,&m)){ memset(G,inf,sizeof(G)); while(m--){ scanf("%d%d%d",&x,&y,&w); G[x][y]=G[y][x]=w; } printf("%d\n",prim(G,n)); } }
Kruskal
#include<iostream> #include<cstring> #include<string> #include<cstdio> #include<algorithm> using namespace std; #define MAX 50005 int father[MAX], son[MAX]; int v, l; typedef struct Kruskal //存储边的信息 { int a; int b; int value; }; bool cmp(const Kruskal & a, const Kruskal & b) { return a.value < b.value; } int unionsearch(int x) //查找根结点+路径压缩 { return x == father[x] ? x : unionsearch(father[x]); } bool join(int x, int y) //合并 { int root1, root2; root1 = unionsearch(x); root2 = unionsearch(y); if(root1 == root2) //为环 return false; else if(son[root1] >= son[root2]) { father[root2] = root1; son[root1] += son[root2]; } else { father[root1] = root2; son[root2] += son[root1]; } return true; } int main() { int ncase, ltotal, sum, flag; Kruskal edge[MAX]; scanf("%d%d", &v, &l); ltotal = 0, sum = 0, flag = 0; for(int i = 1; i <= v; ++i) //初始化 { father[i] = i; son[i] = 1; } for(int i = 1; i <= l ; ++i) { scanf("%d%d%d", &edge[i].a, &edge[i].b, &edge[i].value); } sort(edge + 1, edge + 1 + l, cmp); //按权值由小到大排序 for(int i = 1; i <= l; ++i) { if(join(edge[i].a, edge[i].b)) { ltotal++; //边数加1 sum += edge[i].value; //记录权值之和 //cout<<edge[i].a<<"->"<<edge[i].b<<endl; } if(ltotal == v - 1) //最小生成树条件:边数=顶点数-1 { flag = 1; break; } } if(flag) printf("%d\n", sum); else printf("data error.\n"); return 0; }