题目连接
node
开始的想法是图中一个环内,若是最大的两条边相同,那么就应该删除其中一条;作法是: (1)将边从小到大排序,以后并查集合并x,y; (2)用p[fx]维护并查集最大的边; (3)若是fx==fy且当前边权值w==p[fx],说明应该删除这条边 这个想法是错误,这个在并查集上最大的边不必定在环上
看了别人是这样作的 (1)将边从大到小排序 (2)对于相同权值的边统一考虑,若这条边上两点不连通开始所有加入ans中;而后在考虑重复加入的状况,也是逐渐加入这些权值相同的边,若两点不连通ans-=w; 不然说明这条边不惟一,应该删去
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=2e5+7; struct node{ int x,y; int w; bool operator<(const node& a) const { return w<a.w; } }; node e[N]; int fa[N]; int n,m; LL ans=0; int find_fa(int x) { if(fa[x]!=x) fa[x]=find_fa(fa[x]); return fa[x]; } int main() { scanf("%d %d",&n,&m); for(int i=1;i<=m;i++) scanf("%d %d %d",&e[i].x,&e[i].y,&e[i].w); for(int i=1;i<=n;i++) fa[i]=i; sort(e+1,e+1+m); for(int i=1;i<=m;) { int w=e[i].w; int j=i; while(j<=m&&e[j].w==w) j++; for (int k=i;k<j;k++) { int fx=find_fa(e[k].x); int fy=find_fa(e[k].y); if(fx!=fy) ans+=w; } for (int k=i;k<j;k++) { int fx=find_fa(e[k].x); int fy=find_fa(e[k].y); if(fx!=fy) { fa[fx]=fy; ans-=w; } } i=j; } printf("%lld\n",ans); return 0; }