题目大意:给出一张图,看能形成几个生成树

解题思路:先推断是否能形成生成树,在推断是否有次小生成树

#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;
}