3 1 2 1 1 3 2 2 3 4 4 1 2 1 1 3 4 1 4 1 2 3 3 2 4 2 3 4 5 0
3 5Huge input, scanf is recommended.HintHint
用的Kruskal算法,把边按权值从小到大到大排好序,每次取最小的边,用并查集的思想查找与边相连的两个顶点是否有相同的根,如果没有则相连。
写代码的时候犯了一个错误:
for(int i=1;i<=m;i++) { int x=node[i].from; int y=node[i].to; if(find(x)==find(y)) continue; else { len+=node[i].edge; parent[x]=y; } }
1 2 1
1 3 2
2 3 4 parent[1]=2 ,parent[1]=3 ,parent[2]=3,这样明显是不对的,
正确的应该是这样的,第一行以后,parent[1]=2,第二行,find(1)=2 find(3)=3 2!=3 ,则parent[2]=3,1的根节点为2,第三行,find(2)=3,find(3)=3, 3==3 continue;
代码:
#include <iostream> #include <algorithm> #include <string.h> #include <stdio.h> using namespace std; const int maxn=50010; int parent[110]; int n; struct Node { int from,to,edge; }node[maxn]; void init(int n) { for(int i=1;i<=n;i++) parent[i]=i; } int find(int x) { return parent[x]==x?x:find(parent[x]); } bool cmp(Node a,Node b) { if(a.edge<b.edge) return true; return false; } int main() { while(scanf("%d",&n)!=EOF&&n) { int m=n*(n-1)/2; for(int i=1;i<=m;i++) scanf("%d%d%d",&node[i].from,&node[i].to,&node[i].edge); init(n); sort(node+1,node+1+m,cmp); int len=0; for(int i=1;i<=m;i++) { int x=find(node[i].from); int y=find(node[i].to); if(x==y) continue; else { len+=node[i].edge; parent[x]=y; } } printf("%d\n",len); } return 0; }