您的位置:首页 > 产品设计 > UI/UE

POJ 1679 The Unique MST (次小生成树)

2016-03-22 23:18 435 查看
题目链接:http://poj.org/problem?id=1679

有t组数据,给你n个点,m条边,求是否存在相同权值的最小生成树(次小生成树的权值大小等于最小生成树)。

先求出最小生成树的大小,把最小生成树的边存起来。然后分别枚举最小生成树上的每条边,除了这条边,其他边是否能生成最小生成树,若生成树的权值等于原来最小生成树的权值,则不唯一,否则输出最小生成树的权值。这里我用kruskal比较方便。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int MAXN = 105;
const int INF = 1e9;
struct edge {
int u , v , cost;
}a[MAXN * MAXN];
typedef pair <int , int> P;
int par[MAXN] , f;
bool vis[MAXN][MAXN];
vector <P> G;

void init(int n) {
for(int i = 1 ; i <= n ; i++) {
par[i] = i;
}
memset(vis , false , sizeof(vis));
f = 0;
G.clear();
}

bool cmp(edge a , edge b) {
return a.cost < b.cost;
}

int Find(int n) {
if(par
== n)
return n;
return (par
= Find(par
));
}

int kruskal(int m , int n) {
int res = 0 , cont = n;
for(int i = 1 ; i <= m ; i++) {
if(cont == 1)
break;
else if(vis[a[i].u][a[i].v])
continue;
int u = Find(a[i].u) , v = Find(a[i].v);
if(u != v) {
if(!f) {
G.push_back(P(a[i].u , a[i].v)); // f等于0的时候是求最小生成树的时候,存边操作
}
par[u] = v;
res += a[i].cost;
cont--;
}
}
if(cont == 1)
return res;
return INF;
}

int main()
{
int t , n , m , u , v , w;
scanf("%d" , &t);
while(t--) {
scanf("%d %d" , &n , &m);
init(n);
for(int i = 1 ; i <= m ; i++) {
scanf("%d %d %d" , &u , &v , &w);
a[i].u = u , a[i].v = v , a[i].cost = w;
}
sort(a + 1 , a + m + 1 , cmp);
int res = kruskal(m , n) , check = 0;
f++;
for(int i = 0 ; i < G.size() ; i++) {
for(int j = 1 ; j <= n ; j++) {
par[j] = j;
}
vis[G[i].first][G[i].second] = true;
if(res == kruskal(m , n)) {
check = 1;
break;
}
vis[G[i].first][G[i].second] = false;
}
if(check) {
printf("Not Unique!\n");
}
else {
printf("%d\n" , res);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: