题目大意:求最小生成树但可以减去一条边(当然要减最大的那个了)。
思路:可以用并查集来存图,找出最大值,用是否为父亲节点来判断是否为新的点。再次遍历一遍,pre[]数组置-1,如果有先判断是否产生环(判断pre[]是否相等)。再判断是否大于等于最大值,是的话就多出一种。否则就u的父亲节点归到v的父亲节点的门下,继续遍历。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+10;
int head[maxn],cnt;
int want[maxn],pos,max1;
int n,m,k,ans,pre[maxn];
struct node
{
int u,v,w;
} a[maxn];
struct nod
{
int to,w,next;
}e[maxn];
void addedge(int u,int v,int w)
{
e[cnt].to=v;
e[cnt].w=w;
e[cnt].next=head[u];
head[u]=cnt++;
}
int cmp(node a,node b)
{
return a.w<b.w;
}
int root(int x)
{
if(x!=pre[x])
{
pre[x]=root(pre[x]);
}
return pre[x];
}
void join(int a,int b,int w)
{
int x=root(a);
int y=root(b);
if(x!=y)//不相等就代表时加入了带有新点的边
{
pre[x]=y;
want[pos++]=w;
max1=w;
k++;
ans+=w;
}
}
signed main()
{
memset(head,-1,sizeof(head));
cin>>n>>m;
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
for(int i=0;i<m;i++)
{
int u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
a[i].u=u;
a[i].v=v;
a[i].w=w;
}
sort(a,a+m,cmp);
int i=0;
while(k<n-1)
{
join(a[i].u,a[i].v,a[i].w);
i++;
}
for(int i=1;i<=n;i++)
{
pre[i]=i;
}
int tot=0;
for(int i=0;i<m;i++)
{
if(root(a[i].u)!=root(a[i].v))//防止成环
{
if(a[i].w>=max1)
{
tot++;
}
else
{
pre[root(a[i].u)]=root(a[i].v);
}
}
}
cout<<ans-max1<<" "<<tot<<endl;
return 0;
}