最小生成树的唯一性
Description
给定一个带权无向图,如果是连通图,则至少存在一棵最小生成树,有时最小生成树并不唯一。本题就要求你计算最小生成树的总权重,并且判断其是否唯一。
Input
首先第一行给出两个整数:无向图中顶点数 N(≤500)和边数 M。随后 M 行,每行给出一条边的两个端点和权重,格式为“顶点1 顶点2 权重”,其中顶点从 1 到N 编号,权重为正整数。题目保证最小生成树的总权重不会超过 230。
Output
如果存在最小生成树,首先在第一行输出其总权重,第二行输出“Yes”,如果此树唯一,否则输出“No”。如果树不存在,则首先在第一行输出“No MST”,第二行输出图的连通集个数。
Samples
Input 复制
5 7
1 2 6
5 1 1
2 3 4
3 4 3
4 1 7
2 4 2
4 5 5
Output
11
Yes
Source
浙大版《数据结构学习与实验指导(第2版)》
次小生成树模板:
per数组含义:per[i] = 最小生成树中i结点的前驱结点;
maxx数组含义: maxx[i][j] = 结点i到结点j路径上边权的最大值。
con数组含义:con[i][j] = 1 结点i到结点j这条边入选了最小生成树。
#include<bits/stdc++.h>
#define bug(x) cout<<#x<<" = "<<x<<endl;
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const int inf = 1e9;
int n,m;
vector<pair<int,int> > e[550];
bool vis[550],con[550][550];
int p[550],dis[550],per[550],maxx[550][550];
int Find(int x) {
return x==p[x]?x:p[x]=Find(p[x]);
}
int prim() {
for(int i=1; i<=n; i++) dis[i] = inf;
for(int i=0; i<e[1].size(); i++) {
int to = e[1][i].first;
dis[to] = e[1][i].second;
per[to] = 1;
}
dis[1] = 0;
vis[1] = 1;
int res = 0;
for(int i=1; i<n; i++) {
int u = -1;
int minn = inf;
for(int j=1; j<=n; j++) {
if(!vis[j]&&dis[j]<minn) {
u=j;
minn = dis[j];
}
}
//bug(u);
vis[u] = 1;
con[u][per[u]] = con[per[u]][u] = 1;
res += minn;
maxx[u][per[u]] = maxx[per[u]][u] = minn;
for(int j=1; j<=n; j++)
if(j!=u && vis[j])
maxx[u][j]=maxx[j][u]=max(maxx[j][per[u]],dis[u]);
for(int j=0; j<e[u].size(); j++) {
int to = e[u][j].first;
int val = e[u][j].second;
if(dis[to] > val) {
dis[to] = val;
per[to] = u;
}
}
}
return res;
}
int main() {
cin>>n>>m;
for(int i=1; i<=n; i++) p[i] = i;
for(int i=1; i<=m; i++) {
int u,v,w;
cin>>u>>v>>w;
int dx = Find(u);
int dy = Find(v);
if(dx!=dy) p[dx] = dy;
e[u].push_back({v,w});
e[v].push_back({u,w});
}
int sum = 0;
for(int i=1; i<=n; i++) if(p[i]==i) sum++;
if(sum==1) {
int res = prim();
bool ok = 0;
for(int i=1;i<=n;i++) {
for(int j=0;j<e[i].size();j++) {
int to = e[i][j].first;
int val = e[i][j].second;
if(con[i][to]) continue;
if(val==maxx[i][to]) {
ok=1;
break;
}
}
}
cout<<res<<endl;
if(!ok) printf("Yes");
else printf("No");
} else {
puts("No MST");
cout<<sum;
}
return 0;
}