GYM 100803F(CSU 2097) There is No Alternative(枚举+最小生成树)
题意
求最小生成树上有几条不可替代的边。
解题思路
这个题就是求最小生成树上的割。首先求一次最小生成树是必须的,这里我们可以把这个最小生成树上的边记下来。然后我们再来看,我们可以枚举每条最小生成树上的边再做最小生成树,如果不能构成最小生成树或者构成的最小生成树不等于原先的最小生成树,那么这条边就是割,时间复杂度是O(n*mlogm)。
代码
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
using namespace std;
#define maxn 50005
int n,m,num,sum;
struct line
{
int a,b,val;
} arr[maxn];
int flag[maxn],side[505],p[505],ans;
int cmp(line a,line b)
{
return a.val<b.val;
}
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
int kruskal(int cur)
{
for(int i=0; i<=n; i++)
p[i]=i;
int cnt=0,su=0;
for(int i=0; i<m; i++)
{
if(!flag[i]&&cur!=-1) continue;
int xx=find(arr[i].a);
int yy=find(arr[i].b);
if(xx!=yy)
{
if(cur==-1) side[cnt]=i;
p[xx]=yy;
su+=arr[i].val;
cnt++;
}
if(cnt==n-1) return su;
}
return -1;
}
int main()
{
// freopen("in.txt","r",stdin);
ios::sync_with_stdio(false);
while(cin>>n>>m)
{
for(int i=0; i<m; i++)
cin>>arr[i].a>>arr[i].b>>arr[i].val;
for(int i=0; i<m; i++) flag[i]=1;
sort(arr,arr+m,cmp);
ans=kruskal(-1);
num=sum=0;
for(int i=0; i<n-1; i++)
{
flag[side[i]]=0;
int emsp=kruskal(side[i]);
if(emsp!=ans){
num++;
sum+=arr[side[i]].val;
}
flag[side[i]]=1;
}
cout<<num<<" "<<sum<<endl;
}
return 0;
}