题目大意:给出一张图,看能形成几个生成树
解题思路:先推断是否能形成生成树,在推断是否有次小生成树
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
#define N 110
#define M 410
#define INF 0x3f3f3f3f
struct Edge{
int from, to, cost, next;
}E[M];
int head[N], d[N], maxcost[N][N], id[M], f[N];
int tot, n, m;
bool mark[N], vis[M];
void AddEdge(int u, int v, int c) {
E[tot].from = u; E[tot].to = v; E[tot].cost = c; E[tot].next = head[u]; head[u] = tot++;
u = u ^ v; v = u ^ v; u = u ^ v;
E[tot].from = u; E[tot].to = v; E[tot].cost = c; E[tot].next = head[u]; head[u] = tot++;
}
void init() {
memset(head, -1, sizeof(head));
tot = 0;
scanf("%d%d", &n, &m);
int u, v, c;
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &u, &v, &c);
AddEdge(u, v, c);
}
}
int Prim() {
for (int i = 1; i <= n; i++)
d[i] = INF;
memset(vis, 0, sizeof(vis));
memset(mark, 0, sizeof(mark));
d[1] = 0;
f[1] = 1;
vector<int> v;
int ans = 0;
for (int i = 1; i <= n; i++) {
int t = INF, x;
for (int j = 1; j <= n; j++)
if (!mark[j] && d[j] < t)
t = d[x = j];
if (t == INF) {
return -1;
}
mark[x] = true;
if (x != 1) {
vis[id[x]] = vis[id[x] ^ 1] = true;
ans += E[id[x]].cost;
}
int size = v.size();
for (int j = 0; j < size; j++)
maxcost[v[j]][x] = maxcost[x][v[j]] = max(maxcost[v[j]][f[x]], E[id[x]].cost);
v.push_back(x);
for (int j = head[x]; ~j; j = E[j].next) {
int v = E[j].to;
if (!mark[v] && E[j].cost < d[v]) {
d[v] = E[j].cost;
id[v] = j;
f[v] = x;
}
}
}
return ans;
}
int cas = 1;
void solve() {
printf("Case #%d : ", cas++);
int ans = Prim();
if (ans == -1) {
printf("No way\n");
return ;
}
bool flag = false;
int ans2 = INF, u, v;
for (int i = 0; i < tot; i += 2) {
if (!vis[i]) {
u = E[i].from;
v = E[i].to;
ans2 = min(ans2, ans - maxcost[u][v] + E[i].cost);
}
}
if (ans2 == INF)
printf("No second way\n");
else
printf("%d\n", ans2);
}
int main() {
int test;
scanf("%d", &test);
while (test--) {
init();
solve();
}
return 0;
}