原题链接:http://poj.org/problem?id=1679
题意:
给出n个点,m条边,判断其最小生成树是否唯一。
思路就是求出最小生成树(MST),再求次小生成树,如果两值相等,说明不唯一。应该是次小生成树的模板题了。
#define _CRT_SECURE_NO_DEPRECATE
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
int p[105][105];
bool vis[105];
int lowCost[105];
bool used[105][105];//标记该边是否是最小生成树的一条边
int maxx[105][105];
int pre[105];
int n, m;
int prim()
{
int ans = 0;
memset(vis, 0, sizeof(vis));
memset(used, 0, sizeof(used));
for (int i = 1; i <= n; i++)
{
lowCost[i] = p[1][i];//默认1为起点
pre[i] = 1;
}
vis[1] = 1;
for (int i = 1; i < n; i++)
{
int minn = 99999999;
int minPos;
for (int j = 1; j <= n; j++)
{
if (!vis[j] && lowCost[j] < minn)
{
minn = lowCost[j];
minPos = j;
}
}
ans += minn;
vis[minPos] = 1;
used[pre[minPos]][minPos] = used[minPos][pre[minPos]] = 1;
for (int j = 1; j <= n; j++)
{
if (vis[j] && j != minPos)
maxx[j][minPos] = maxx[minPos][j] = max(maxx[j][pre[minPos]], lowCost[minPos]);
if (!vis[j] && lowCost[j] > p[minPos][j])
{
lowCost[j] = p[minPos][j];
pre[j] = minPos;
}
}
}
return ans;
}
int main()
{
int t;
int u, v, w;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
p[i][j] = 99999999;
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &u, &v, &w);
p[u][v] = p[v][u] = w;
}
int MST = prim();
int MST2 = 99999999;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
{
if (!used[i][j])
{
MST2 = min(MST2, MST + p[i][j] - maxx[i][j]);
}
}
}
if (MST != MST2)
printf("%d\n", MST);
else
printf("Not Unique!\n");
}
return 0;
}