题意
给出一个无向带权连通图,在不改变原来最小生成树权值的条件下,可以将任意的几条边的权值加1,操作次数不限,要求获得的最小生成树是唯一的,求出最小需要改变的次数。
题解
参考:https://www.cnblogs.com/shuaihui520/p/10320158.html
ac代码:
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
#define M_PI 3.14159265358979323846
int fa[200005];
struct node{
int u,v;
ll w;
}e[200005];
int cmp(node x,node y)
{
return x.w<y.w;
}
int find(int x)
{
return x==fa[x]? x:fa[x]=find(fa[x]);
}
void merge(int x,int y)
{
int fx=find(x),fy=find(y);
if(fx!=fy)
fa[x]=fy;
}
int main()
{
ios::sync_with_stdio(false);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=0;i<m;i++)
cin>>e[i].u>>e[i].v>>e[i].w;
sort(e,e+m,cmp);
int ans=0;
for(int i=0;i<m;)
{
int j=i,num=0;
while(e[j].w==e[i].w)
j++;
for(int k=i;k<j;k++)
{
int fu=find(e[k].u),fv=find(e[k].v);
if(fu!=fv)
num++;
}
for(int k=i;k<j;k++)
{
int fu=find(e[k].u),fv=find(e[k].v);
if(fu!=fv)
merge(fu,fv),num--;
}
i=j;
ans+=num;
}
cout<<ans<<endl;
return 0;
}