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

Poj 1679 The Unique MST

2012-08-18 14:07 267 查看
题目描述:

给定一个连通无向网,判定它的最小生成树是否唯一。

输入描述:

输入文件的第1 行为一个整数t,1≤t≤20,表示测试数据的数目。每个测试数据描述了一个

连通无向网。每个测试数据的第1 行为两个整数:n 和m,1≤n≤100,分别表示顶点的数目和

边的数目。接下来有m 行,每行为一个三元组(xi, yi, wi),表示一条边(xi, yi),xi 和yi 表示边的两

个顶点,顶点序号从1 开始计起,这条边的权值为wi。任何两个顶点间最多只有一条边。

输出描述:

对输入文件中的每个测试数据,如果最小生成树是唯一的,则输出最小生成树的权;如果最

小生成树不唯一,则输出"Not Unique!"。

模版判断是否是唯一的最小生成树。这里借鉴一下:

判定最小生成树是否唯一的一个正确思路为:

1) 对图中每条边,扫描其他边,如果存在相同权值的边,则对该边作标记;

2) 然后用Kruskal 算法(或Prim 算法)求MST;

3) 求得MST 后,如果该MST 中未包含作了标记的边,即可判定MST 唯一;如果包含作了

标记的边,则依次去掉这些边再求MST,如果求得的MST 权值和原MST 的权值相同,即可判定

MST 不唯一。

so~~~~

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#define MAX 10500
#define INF 0x7FFFFFFF
# define eps 1e-5
using namespace std;
struct Edge//边的信息:起点 终点 权值 是否访问 是否删去 是否存在权值相等
{
int s,e,value;
int vis,del,equal;
} edge[MAX];
int n,m,par[105];
int mst;//第一次mst的标志
int find(int x)//查
{
while(par[x] != x)
x = par[x];
return x;
}
void connect(int a,int b)//并
{
if(a < b)
par[b] = a;
else
par[a] = b;
}
bool cmp(Edge a, Edge b)//比
{
return a.value < b.value;
}
int kruskal()
{
int i,j,sum = 0;
for(i=1; i<=n; i++)
par[i] = i;
for(i=1; i<=m; i++)
{
int a = find(edge[i].s);
int b = find(edge[i].e);
if(!edge[i].del && a != b)
{
connect(a,b);
sum += edge[i].value;
if(mst == 1)
{
edge[i].vis = 1;
}
}
}
return sum ;
}
int main()
{
int t,i,j;
scanf("%d",&t);
while(t --)
{
scanf("%d%d",&n,&m);
for(i=1; i<=m; i++)//初始化以及构图
{
scanf("%d%d%d",&edge[i].s,&edge[i].e,&edge[i].value);
edge[i].del = 0;
edge[i].vis = 0;
edge[i].equal = 0;
}
for(i=1; i<=m; i++)//找出有相等权值的边
for(j=1; j<=m; j++)
{
if(i != j && edge[i].value == edge[j].value)
{
edge[i].equal = 1;
}
}
sort(edge+1,edge+1+m,cmp);
mst = 1;
int sum1 = kruskal();
int ok = 1;//作为是否mst不唯一的标志
mst = 0;
for(i=1; i<=m; i++)
{
if(edge[i].vis && edge[i].equal )
{
edge[i].del = 1;//依次去掉权值相等的边,再求mst
int sum2 = kruskal();
if(sum2 == sum1)//两次权值相等
{
printf("Not Unique!\n");
ok = 0;
break;
}
edge[i].del = 0;//删去的边补回来
}
}
if(ok == 1)
{
printf("%d\n",sum1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  测试 算法