题意:给出n点,m条边,要求输出最小生成树,且存在最小生成树的值相同的最小生成树时输出Not Unique!
题解:这里写的是Prime-邻接矩阵(以前使用的模板,后来都是手码了~)
代码如下:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
const int maxn = 1e3;
int mp[maxn][maxn];
int vis[maxn];
int dis[maxn];
int n;
bool More(int u, int MIN) //如果被访问的边有不止一条相同,则说明有不止一种方法
{
int cnt = 0;
for (int j = 1; j <= n; j++)
if (vis[j] && mp[u][j] == MIN)
cnt++;
return cnt > 1;
}
void prim()
{
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++)
dis[i] = mp[1][i];
int u = 1;
vis[u] = 1;
int ans = 0;
int key = 0;
for (int i = 1; i < n; i++)//n-1次增点
{
int MIN = inf;
for (int j = 1; j <= n; j++)
if (!vis[j] && dis[j] < MIN)
{
MIN = dis[j];
u = j;
}
if (More(u, MIN))
{
key = 1; break; //如果存在增同一点多条最短边则随便MST不唯一
}
if (MIN == inf) return; //如果无法延伸说明无法构成MST
ans += MIN;
vis[u] = 1;
for (int j = 1; j <= n; j++)
if (dis[j]>mp[u][j] && !vis[j])
dis[j] = mp[u][j];
}
if (key)
cout << "Not Unique!" << endl;
else
cout << ans << endl;
}
void input()
{
int u, v, w, m;
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = i; j <= n; j++)
{
if (i == j)
mp[i][j] = 0;
else
mp[j][i] = mp[i][j] = inf;
}
while (m--)//添加m条无向边
{
scanf("%d%d%d", &u, &v, &w);
mp[u][v] = mp[v][u] = min(mp[v][u], w);
}
}
int main()
{
int t;
scanf("%d", &t);
while (t--)
{
input();
prim();
}
return 0;
}