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

POJ 1679 The Unique MST(判断最小生成树是否唯一)

2016-04-04 14:02 591 查看

题目链接:POJ 1679 The Unique MST

POJ 1679 The Unique MST(判断最小生成树是否唯一)

思路:枚举删边,再求最小生成树,相等则不唯一

判断最下生成树是否唯一的思路一:

1、对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记。

2、然后用Kruskal算法或Prim算法求MST。

3、求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一;如果包含做了标记的边,则依次去掉这些边再求MST,如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一。

判断最下生成树是否唯一的思路二:(较为复杂)

首先求出原图最小生成树,权值之和为min 枚举添加每条不在最小生成树上的边 ,加上以后一定会形成一个环。

找到环上除了(u,v)以外的权值最大的边,把它删掉,计算当前生成树的权值之和。 枚举完所有边之后,得到的最小值即为次小生成树的权值。

具体实现时,更简单的方法是从每个节点i遍历整个最小生成树

定义F[i][j]为在生成树上,从i到j的路径上最大的边的权值。通过BFS,求出F[i][j]的值

然后对于添加每条不在最小生成树中的边(i,j),并删去该环中的原生成树的的最大边。 新的生成树权值之和就是Min + w(i,j) –

F[i][j] 记录其最小值,则为次小生成树。

次小生成树详解点这里

鄙人愚钝,用的删边枚举:

当且仅当第i条边与第j条边的权值相等,且MST中包含第i条边时,删去第i条边,再求MST.可以减掉多次枚举

/*************************************************************************
> File Name: poj_1679.cpp
> Author: dulun
> Mail: dulun@xiyoulinux.org
> Created Time: 2016年04月03日 星期日 17时38分34秒
************************************************************************/

#include<iostream>
#include<stdio.h>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
const int N = 50086;

bool first = 0;
int n, m;
int p
;
struct Edge
{
int s, e, w;
bool same, use, del;
};
Edge e
;

bool cmp(Edge a, Edge b) { return a.w < b.w; }
int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); }

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

int kruscal()
{
int cnt = 0, ans = 0;
init();
for(int i = 0; i < m; i++)
{
if(e[i].del == true) continue;
int x = find(e[i].s);
int y = find(e[i].e);
if( x!=y )
{
p[x] = y;
ans+=e[i].w;
if(first) e[i].use = true;
cnt++;
}
if(cnt == n-1) return ans;
}
return ans;
}

void findSameWeight()
{
for(int i = 0; i < m; i++)
for(int j = 0; j < m; j++)
{
if(i==j) continue;
if(e[i].w == e[j].w) e[i].same = true;
}
}

void sovle()
{
sort(e, e+m, cmp);
first = true;
int ans_MST = kruscal();
first = false;
for(int i = 0; i < m; i++)
{
if(e[i].use && e[i].same)
{
e[i].del = true;
int ans = kruscal();
e[i].del = false;
if(ans == ans_MST)
{
printf("Not Unique!\n");
return ;
}
}
}
printf("%d\n", ans_MST);
return;
}

int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++)
{
int a, b, w;
scanf("%d%d%d", &a, &b, &w);
e[i].s = a, e[i].e = b, e[i].w = w;
e[i].same = false;
e[i].use = false;
e[i].del = false;
}
findSameWeight();
sovle();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 kruskal