https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1541
给出一个图,让你求MST和次小生成树,且次小生成树必存在。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int t, n, m, Min, mst, f[10005];
struct Edge {
int u, v;
int weig;
} edge[11000];
void makeset()
{
for(int i = 0; i <= n; i++)
f[i] = i;
}
int _find(int x)
{
return f[x] = x == f[x] ? x : _find(f[x]);
}
int kruskal()
{
makeset();
int cnt = 0, path[110]; //记录MST的边
for(int i = 0; i < m; i++) {
int u = _find(edge[i].u);
int v = _find(edge[i].v);
if(u != v) {
f[u] = v;
mst += edge[i].weig;
path[cnt++] = i;
}
}
for(int k = 0; k < cnt; k++) {
int count = 0, ans = 0;
makeset();
for(int i = 0; i < m; i++) {
if(i == path[k])
continue;
int u = _find(edge[i].u);
int v = _find(edge[i].v);
if(u != v) {
f[u] = v;
count++;
ans += edge[i].weig;
}
}
if(count == n - 1) { //如果能构成树,求最小的ans
if(Min > ans) {
Min = ans;
}
}
}
}
bool cmp(Edge x, Edge y)
{
return x.weig < y.weig;
}
int main()
{
scanf("%d", &t);
while(t--) {
scanf("%d%d", &n, &m);
for(int i = 0; i < m; i++) { //输入边的顶点及权值
scanf("%d%d%d", &edge[i].u, &edge[i].v, &edge[i].weig);
}
mst = 0;
Min = 2147483647;
sort(edge, edge + m, cmp);
kruskal();
printf("%d %d\n", mst, Min);
}
return 0;
}