1. 程式人生 > 實用技巧 >The Unique MST[不嚴格的次小生成樹]

The Unique MST[不嚴格的次小生成樹]

Aimee

好不容易得到了這個稱號,彆著急摘下來
--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;
}