题意:有n个岛,n-1个桥,任意两个岛之间都可通过桥到达,所以总共有 n(n-1)/2 条不同的路经,有若干个桥坏了,某一路径上只要有坏了的桥,这条路径就被称为坏路径,现在让你修复其中一条或是不修,使剩下的坏的路径数最少!
算法:并查集
关键数组:flag[i]用于记录根节点为i的集合中的元素个数;
错点:类型转换。因为数比较大,所以选择了long long 类型,这里在把int 型的数据复制给long long 型时,需要强制转换,否则错误;
#include <iostream> using namespace std; const int Max=200011; struct node { int s; int t; }map[200011]; int flag[Max]; int bing[Max]; int fnd(int r) { int a=r,b; while(r!=bing[r]) r=bing[r]; while(a!=r) { b=bing[a]; bing[a]=r; a=b; } return r; } void merg(int x,int y) { x=fnd(x); y=fnd(y); if(x!=y) { bing[x]=y; flag[y]=flag[y]+flag[x]; } } int main() { int i,j; //long n=200000*10000; //cout<<"test:"<<n<<endl; //printf("%ld",n); int n; while(scanf("%d",&n)!=EOF) { for(i=1;i<=n;i++) { bing[i]=i; flag[i]=1; } int a,b,c; int number=0; for(i=1;i<n;i++) { cin>>a>>b>>c; if(c==0) merg(a,b); if(c==1) { map[number].s=a; map[number].t=b; number++; } } long long max=0; long long temp=0; int f1=0,f2=0; for(i=0;i<number;i++) { a=fnd(map[i].s); b=fnd(map[i].t); int k=0; k=flag[a]+flag[b]; temp=(long long)k*(k-1)/2; if(max<temp) { max=temp; f1=a; f2=b; } } long long sum=0; for(i=1;i<=n;i++) { if(bing[i]==i&&i!=f1&&i!=f2) sum+=(long long)flag[i]*(flag[i]-1)/2; } long long N= (long long)n*(n-1)/2; N=N-max-sum; printf("%lld\n",N); } return 0; }