标签:data- str 数据规模 NPU include merge 数据 output algo
如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz
第一行包含两个整数N、M,表示该图共有N个结点和M条无向边。(N<=5000,M<=200000)
接下来M行每行包含三个整数Xi、Yi、Zi,表示有一条长度为Zi的无向边连接结点Xi、Yi
输出包含一个数,即最小生成树的各边的长度之和;如果该图不连通则输出orz
4 5 1 2 2 1 3 2 1 4 3 2 3 4 3 4 3
7
时空限制:1000ms,128M
数据规模:
对于20%的数据:N<=5,M<=20
对于40%的数据:N<=50,M<=2500
对于70%的数据:N<=500,M<=10000
对于100%的数据:N<=5000,M<=200000
#include<iostream> #include<algorithm> using namespace std; const int inf=200000; struct node{ int u,v,w; }; struct node e[inf]; int n,m,f[inf],sum=0,cnt=0; bool cmp(node t1,node t2) { return t1.w<t2.w; } int find(int x) { if(x!=f[x]) return f[x]=find(f[x]); else return x; } int merge(int x,int y) { int x1=find(x); int y1=find(y); if(x1!=y1) { f[y1]=x1; return 1; } return 0; } int main() { int t1,t2; cin>>n>>m; for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { cin>>e[i].u>>e[i].v>>e[i].w; merge(e[i].u,e[i].v); } cnt=0; for(int i=1;i<=n;i++) { if(f[i]==i) cnt++; } if(cnt!=1) { cout<<cnt<<endl; cout<<"orz"<<endl; return 0; } for(int i=1;i<=m;i++) f[i]=i; cnt=0; sort(e+1,e+m,cmp); for(int i=1;i<=m;i++) { if(merge(e[i].u,e[i].v)) { cnt++; sum=sum+e[i].w; } if(cnt==n-1) { break; } } cout<<sum<<endl; return 0; }
从边开始找
first 给所有的边从小到大排序
找的边要满足这样的条件 边的两点属于不同的连通分量(使用并查集)
找到n-1条边就行了
这就是克鲁斯卡尔算法
标签:data- str 数据规模 NPU include merge 数据 output algo
原文地址:https://www.cnblogs.com/liuzhaojun/p/11280457.html