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

[POJ1679]The Unique MST 次小生成树

2015-11-07 21:16 369 查看
题目链接:http://poj.org/problem?id=1679

  给你一个图的连通情况,询问你此图的最小生成树是否唯一。

  假如最小生成树唯一,即生成树连通所有节点的权值和唯一。假如不唯一,那么存在另一条最小生成树使得权值等于之前最小生成树的权值。

  换个思路考虑,也就是次小生成树的权值与最小生成树的权值相同,那么问题就变成了求次小生成树的权值。

  我选择的是先求出最小生成树,将树上用到的边都保存下来。接着分别将每一条用到的边摘下来,再求一次最小生成树。假如不包含当前删掉的边生成的生成树的所选边权值与最小生成树的所选边权值相同,那么最小生成树就是不唯一的了。

代码:

#include <algorithm>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <climits>
#include <complex>
#include <fstream>
#include <cassert>
#include <cstdio>
#include <bitset>
#include <vector>
#include <deque>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>
#include <cmath>

using namespace std;

typedef struct Node {
int u;
int v;
int w;
}Node;

bool cmp(Node n1, Node n2) {
return n1.w < n2.w;
}

const int maxn = 111;
Node node[6666];
int vis[maxn];
int n, m, u, v, w;
int pre[maxn];
int cnt, dig, flag, ans;

void init() {
for(int i = 0; i <= maxn; i++) {
pre[i] = i;
}
}

int find(int x) {
return x == pre[x] ? x : pre[x] = find(pre[x]);
}

void unite(int x, int y) {
x = find(x);
y = find(y);
if(x != y) pre[y] = x;
}

int main() {
// freopen("in", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
init();
memset(vis, 0, sizeof(vis));
memset(node, 0, sizeof(node));
dig = 0;
cnt = 0;
flag = 0;
scanf("%d %d", &n, &m);
for(int i = 0; i < m; i++) {
scanf("%d %d %d", &u, &v, &w);
node[i].u = u;
node[i].v = v;
node[i].w = w;
}
sort(node, node+m, cmp);
for(int i = 0; i < m && cnt < n; i++) {
if(find(node[i].u) != find(node[i].v)) {
unite(node[i].u, node[i].v);
vis[cnt++] = i;
dig += node[i].w;
}
}
ans = dig;

for(int i = 1; i < n; i++) {
init();
cnt = n - 1;
dig = 0;
for(int j = 0; j < m && cnt; j++) {
if(vis[i] != j && find(node[j].u) != find(node[j].v)) {
unite(node[j].u, node[j].v);
dig += node[j].w;
cnt--;
}
}
if(cnt == 0 && dig == ans) {
flag = 1;
break;
}
}

if(flag) printf("Not Unique!\n");
else printf("%d\n", ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: