poj 1679 The Unique MST

题意:给定一个连通的无向图,判断最小生成树是否唯一。


思路:

1.对于图中每条边,把存在相同权值的边作一个标记。

2.然后求出MST。

3.求的MST后如果该MST未包含标记的边,则可判定MST唯一;如果包含了作了标记的边,则一次去掉这些边再求MST,如果求得的MST和原来的MST权值相同,即可判定MST不唯一。


代码:

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 105;
const int maxm = 5005;

struct edge{
	int u,v;
	int w;
	bool equal;//是否存在相等的边 
	bool used;//第一次构造时是否使用 
	bool del;//是否删除
	
	bool operator < (const edge &b) const{
		return w < b.w;
	}
};

int n,m;
edge a[maxm];
int p[maxn];
bool fg; //是否是第一次构造 

void UFset(){
	for(int i = 0; i <= n; i++)
		p[i] = -1;
}

int Find(int x){
	return p[x] >= 0 ? p[x] = Find(p[x]) : x;
}

void Union(int r1, int r2){
	r1 = Find(r1);
	r2 = Find(r2);
	int t = p[r1] + p[r2];
	if(p[r1] > p[r2]){
		p[r1] = r2;
		p[r2] = t;
	}
	else{
		p[r2] = r1;
		p[r1] = t;
	}
}

int Kruskal(){
	int sum = 0;
	int num = 0;
	UFset();
	for(int i = 0; i < m; i++){
		if(a[i].del)//这条边已经被去除 
			continue;
		int u = a[i].u, v = a[i].v;
		if(Find(u) != Find(v)){
			Union(u,v);
			sum += a[i].w;
			num++;
			if(fg) a[i].used = true;
		}
		if(num >= n-1)
			break;
	}
	return sum;
} 

int main(){
	int t;
	//freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	cin>>t;
	while(t--){
		cin>>n>>m;
		for(int i = 0; i < m; i++){
			cin>>a[i].u>>a[i].v>>a[i].w;
			a[i].del = false;
			a[i].equal = false;
			a[i].used = false;
		}
		sort(a,a+m);
		
		for(int i = 1; i < m; i++){//标记权值相等的边 
			if(a[i].w == a[i-1].w){
				a[i].equal = true;
				a[i-1].equal = true;
			}
		}
		
		fg = true; 
		int w1 = Kruskal();
		int w2 = -1;
		fg = false;
		
		for(int i = 0; i < m; i++){
			if(a[i].used && a[i].equal){
				a[i].del = true;
				w2 = Kruskal();
				if(w1 == w2){
					cout<<"Not Unique!\n";
					break;
				}
				a[i].del = false;
			}
		}
		if(w1 != w2)
			cout<<w1<<"\n";
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值