判断最小生成树是否唯一, 即求次小生成树, O(nm + mlogm)
还要判断一下图是否联通。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
struct node
{
int u, v, w;
}e[100001];
int n, m;
int f[1001];
bool vis[100001];
bool cmp(const node &a, const node &b)
{
return a.w < b.w;
}
int find(int x)
{
if (x != f[x])
f[x] = find(f[x]);
return f[x];
}
int kruscal()
{
int sum = 0;
for (int i = 1; i <= n; i++)
f[i] = i;
for (int i = 1; i <= m; i++)
{
int x = find(e[i].u), y = find(e[i].v);
if (x != y)
{
sum += e[i].w;
f[y] = x;
vis[i] = true;
}
}
return sum;
}
int kruscal2(int k)
{
int sum = 0, cnt = 0;
for (int i = 1; i <= n; i++)
f[i] = i;
for (int i = 1; i <= m; i++)
{
if (i == k)
continue;
int x = find(e[i].u), y = find(e[i].v);
if (x != y)
{
sum += e[i].w;
f[y] = x;
cnt++;
}
}
if (cnt != n - 1)
return -1;
return sum;
}
int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d %d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d %d %d", &e[i].u, &e[i].v, &e[i].w);
sort(e + 1, e + m + 1, cmp);
memset(vis, 0, sizeof(vis));
int ans = kruscal();
bool flag = true;
for (int i = 1; i <= m; i++)
if (vis[i])
if (kruscal2(i) == ans)
{
flag = false;
break;
}
if (flag)
printf("%d\n", ans);
else
printf("Not Unique!\n");
}
return 0;
}
本文介绍了一种算法,用于判断图的最小生成树是否唯一,并通过求次小生成树来实现这一目标。该算法首先确保图是连通的,然后使用Kruskal算法找出最小生成树,并检查移除每条边后的生成树总权重是否发生变化,以此判断最小生成树的唯一性。
1万+

被折叠的 条评论
为什么被折叠?



