The Unique MST[不嚴格的次小生成樹]
阿新 • • 發佈:2020-11-03
好不容易得到了這個稱號,彆著急摘下來
--scz
你也可以不用次小生成樹做
但是也可以
次小生成樹和最小一樣大就證明不止一個
次小生成樹要是不嚴格的話,只需要在求出的最小生成樹上,加入一條新邊,然後生成了一個環,在這個環上呢,刪掉最大的邊就行了
然後在最小生成樹上加一點點東西就夠了
存一下任意兩點之間的最大的那條邊
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<vector> using namespace std; int n; int t,m; struct b{ int f; int to; int v; }ed[20010]; vector<int> po[110]; //vector是個好東西 int fa[110],maxe[110][110]; int vis[110]; int read(){ int res=0; int f=1; char c=getchar(); while(c!='-'&&(c<'0'||c>'9')) c=getchar(); if(c=='-') f=-1,c='0'; while(c>='0'&&c<='9') res=(res<<1)+(res<<3)+c-'0',c=getchar(); return res*f; } bool cmp(b x, b y){ return x.v<y.v; } int sum; int Aimee; int x,y; int l1,l2; int find(int x){ return fa[x]==x ? x:fa[x]=find(fa[x]); } void kru(){ sum=0; Aimee=0; for(int i=1;i<=m;++i){ if(Aimee==n-1) break; x=find(ed[i].f); y=find(ed[i].to); if(x==y) continue; Aimee++; vis[i]=1; sum+=ed[i].v; l1=po[x].size(); l2=po[y].size(); for(int j=0;j<l1;++j){ for(int k=0;k<l2;++k){ maxe[po[x][j]][po[y][k]]=maxe[po[y][k]][po[x][j]]=ed[i].v; } } //因為kr肯定是越往後的邊越大 //直接賦值就行 fa[x]=y; for(int j=0;j<l1;++j) po[y].push_back(po[x][j]); //合併兩點之間的點 //x還是y無所謂 } int Ar=0x7f7f7f7f; for(int i=1;i<=m;++i){ if(!vis[i]){ Ar=min(Ar,sum+ed[i].v-maxe[ed[i].f][ed[i].to]); } } //列舉刪邊 if(Ar>sum){ cout<<sum<<endl; }else{ cout<<"Not Unique!"<<endl; } } int main(){ t=read(); while(t--){ n=read(); m=read(); for(int i=1;i<=m;++i){ scanf("%d%d%d",&ed[i].f,&ed[i].to,&ed[i].v); vis[i]=0; } sort(ed+1,ed+m+1,cmp); for(int i=1;i<=n;++i){ fa[i]=i; po[i].clear(); po[i].push_back(i); } kru(); } return 0; }