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

判断生成树的唯一性 poj1679 The Unique MST

2016-08-27 23:12 477 查看
【分析】最小生成树的唯一性,思路是先判断每条边是否有重边,有的话eq=1,否则0.然后第一次求出最小生成树,将结果记录下来,
然后依次去掉第一次使用过的且含有重边的边,再求一次最小生成树,若结果与第一次结果一样,则不唯一。


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;

struct node{
int u, v, dis;
bool eq, use, del;

bool operator <(const node &x)const{
return dis < x.dis;
}
};

#define MAXN (100+5)
#define MAXM (20000+5)

int n, m;
node edges[MAXM];
int f[MAXN];

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

int kruscal(bool ok){
for(int i = 1; i <= n; i++) f[i] = i;

int ret = 0, tot = 0;
for(int i = 1; i <= m; i++)
if(!edges[i].del){
int u = edges[i].u, v = edges[i].v, dis = edges[i].dis;
int x = find(u), y = find(v);

if(x != y){
tot++; ret += dis;
f[x] = y;
if(ok) edges[i].use = true;

if(tot >= n-1) break;
}
}
return ret;
}

int main(){
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);

int T;
scanf("%d", &T);

while(T--){
scanf("%d%d", &n, &m);

for(int i = 1; i <= m; i++){
scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].dis);
edges[i].eq = edges[i].use = false;
}

for(int i = 1; i <= m; i++)
for(int j = 1; j <= m; j++)
if(i != j && edges[i].dis == edges[j].dis) edges[i].eq = true;

sort(edges+1, edges+m+1);

bool tmp = true;
int minest = kruscal(tmp);
tmp = false;

bool found = false;
for(int i = 1; i <= m; i++)
if(edges[i].eq && edges[i].use){
edges[i].del = true;

int now = kruscal(tmp);
if(now == minest){
found = true;
printf("Not Unique!\n");
edges[i].del = false;
break;
}

edges[i].del = false;
}

if(!found) printf("%d\n", minest);
}

return 0;
}



                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: