题目:判断是否有唯一一个最小生成树。
1.在网上看了好多的代码。。。板子上kuangbin大神次小生成树的代码竟然就是个求最小生成树的。。。。并不完整。
他的博客上倒是有完整的 先码住
求最小生成树时,用数组Max[i][j]来表示MST中i到j最大边权
求完后,直接枚举所有不在MST中的边,替换掉最大边权的边,更新答案
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define inf 0x3f3f3f3f
#define ms(x) memset(x, 0, sizeof(x))
using namespace std;
const int N = 110;
bool vis[N];
int lowc[N];
int pre[N];
int Max[N][N];
bool used[N][N];
int prime(int cost[][N], int n) //kuangbin的板子
{
int ans = 0;
ms(vis);
ms(Max);
ms(used);
vis[0] = true;
pre[0] = -1;
for(int i=1; i<n; i++)
{
lowc[i] = cost[0][i];
pre[i] = 0;
}
lowc[0] = 0;
for(int i=1; i<n; i++)
{
int mic = inf;
int p = -1;
for(int j=0; j<n; j++)
if(!vis[j] && mic>lowc[j])
{
mic = lowc[j];
p = j;
}
if(mic == inf ) return -1;
ans+=mic;
vis[p] = true;
used[p][pre[p]]= used[pre[p]][p] = true;
for(int j=0; j<n; j++)
{
if(vis[j]) Max[j][p] = Max[p][j] = max(Max[j][pre[p]], lowc[p]);
if(!vis[j] && lowc[j] > cost[p][j])
{
lowc[j] = cost[p][j];
pre[j] = p;
}
}
}
return ans;
}
int ans ;
int smst(int cost[][N], int n) //求次小生成树
{
int mi =inf;
for(int i=0;i<n;i++)
{
for(int j=i+1;j<n;j++)
{
if(cost[i][j]!=inf && !used[i][j])
{
mi = min(mi, ans+cost[i][j] - Max[i][j]);
}
}
}
if(mi == inf) return -1;
return mi;
}
int cost[N][N];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(i==j) cost[i][j] = 0;
else cost[i][j] = inf;
}
}
while(m--)
{
int x, y, z;
scanf("%d%d%d",&x,&y,&z);
x--, y--;
cost[x][y] = cost[y][x] = z;
}
ans = prime(cost,n);
if(ans == -1)
{
printf("Not Unique!\n");
}
else if(ans == smst(cost, n))
printf("Not Unique!\n");
else printf("%d\n",ans);
}
return 0;
}
2.
思路2.1 用prim 时, 如果有两个符合条件且权值相同的边, 则最小生成树不唯一。
2.2 kruskal 先建个最小生成树, 并用个数组记录下边的id。
枚举边,建树时跳过这些边。如果权值一样, 则不唯一