原题链接:​​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;
}