首页 > 代码库 > POJ 1679 The Unique MST 次小生成树

POJ 1679 The Unique MST 次小生成树

题目来源:POJ 1679 The Unique MST

题意:判断最小生成树是否唯一 求出次小生成树比较

思路:慢一点的方法就是求出最小生成树 每次去掉最小生成树的一条边再求最小生成树 比较慢

更好的方法是 求出最小生成树后加上一条没有用到的边 然后必定出现一条回路 去掉回路上权值最大的边 做m-(n-1)次 

求一次最小生成树 然后n^2的时间预处理最小生成树上两点之间最大的边权 最后换边 MST-加进去的边的权值-回路上的最大边权值 取小


#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
const int maxn = 110;
struct edge
{
	int u, v, w;
	edge(){}
	edge(int u, int v, int w): u(u), v(v), w(w){}
}a[100000];
int f[maxn];
int dp[maxn][maxn];
int n, m;
bool ok[100000];
vector <edge> G[maxn];
bool cmp(edge a, edge b)
{
	return a.w < b.w;
}
int find(int x)
{
	if(x != f[x])
		return f[x] = find(f[x]);
	return f[x];
}

int MST()
{
	for(int i = 1; i <= n; i++)
	{
		f[i] = i;
		G[i].clear();
	}
	memset(ok, false, sizeof(ok));
	sort(a, a+m, cmp);
	memset(dp, 0, sizeof(dp));
	int sum = 0;
	for(int i = 0; i < m; i++)
	{
		int u = a[i].u;
		int v = a[i].v;
		int w = a[i].w;
		int x = find(u);
		int y = find(v);
		if(x != y)
		{
			sum += w;
			f[x] = y;
			G[u].push_back(edge(u, v, w));
			G[v].push_back(edge(v, u, w));
			ok[i] = true;
		}
	}
	return sum;
}

void BFS(int x)
{
	queue <edge> Q;
	Q.push(edge(-1, x, 0));
	while(!Q.empty())
	{
		edge u = Q.front(); Q.pop();
		for(int i = 0; i < G[u.v].size(); i++)
		{
			edge v = G[u.v][i];
			if(v.v == u.u)
				continue;
			int temp = max(u.w, v.w);
			dp[x][v.v] = dp[v.v][x] = max(dp[x][v.v], temp);
			Q.push(edge(v.u, v.v, temp));
		}
	}
}
int main()
{
	int T;
	scanf("%d", &T);
	while(T--)
	{
		scanf("%d %d", &n, &m);
		for(int i = 0; i < m; i++)
			scanf("%d %d %d", &a[i].u, &a[i].v, &a[i].w);
		int ans = MST();
		int sum = 999999999;
		for(int i = 1; i <= n; i++)
			BFS(i);
		for(int i = 0; i < m; i++)
		{
			if(ok[i])
				continue;
			int u = a[i].u;
			int v = a[i].v;
			int w = a[i].w;
			sum = min(sum, ans+w-dp[u][v]);
		}
		if(ans == sum)
			puts("Not Unique!");
		else
			printf("%d\n", ans);
	}
	return 0;
}