題目連接
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; }