JDOJ 1229: VIJOS-P1045 Kerry 的电缆网络
https://neooj.com/oldoj/problem.php?id=1229
Description
Input
Output
Sample Input
Sample Output
HINT
1< =n,m< =100000
复习KRUSKAL算法的一道板子题。
用这道题简单介绍一下KRUSKAL算法。
实现原理我觉得是图论算法中最简单的一个。
不是要求最小生成树么?
好,我把边按照边权从小到大排序,当然也可以求最大生成树,从大到小排序不就可以了?
排序完了之后依次枚举每条边,加入到最小生成树中,这里要注意了,我们不能乱加,需要判断加进去的这条边能不能和已经加进去的边构成树,显然的,如果加进去的边和其他的边构成了环,那么就肯定不能把这条边加进树中,我们需要判断能不能构成环,就使用并查集维护即可(即并查集判环)。
有了这些理论知识,AC这道题就很简单了。
Code:
#include<cstdio> #include<algorithm> using namespace std; int n,x,y,j,cnt; double s,z,ans; int fa[100010]; struct city { int x,y; double z; }e[1000010]; bool cmp(city a,city b) { return a.z<b.z; } int find(int x) { if(fa[x]==x) return x; return fa[x]=find(fa[x]); } int main() { scanf("%lf%d",&s,&n); while(scanf("%d%d%lf",&x,&y,&z)!=EOF) { j++; e[j].x=x;e[j].y=y;e[j].z=z; } sort(e+1,e+j+1,cmp); for(int i=1;i<=n;i++) fa[i]=i; for(int i=1;i<=j;i++) { int fx=find(e[i].x); int fy=find(e[i].y); if(fx!=fy) { fa[fx]=fy; cnt++; ans+=e[i].z; } if(cnt==n-1) break; } if(ans<=s && cnt==n-1) printf("Need %.2lf miles of cable",ans); else printf("Impossible"); return 0; }