社区讨论

最小生成树求调

P4208[JSOI2008] 最小生成树计数参与者 3已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@mjy25cy8
此快照首次捕获于
2026/01/03 16:45
2 个月前
此快照最后确认于
2026/01/06 22:55
上个月
查看原帖
CPP
#include <bits/stdc++.h>
#define rep(i, x, y) for (int i = x; i <= y; i++)
#define lop(i, x, y) for (int i = x; i >= y; i--)
#define sort stable_sort
using namespace std;
typedef long double ld;
const int MOD = 31011;
const int NR = 105;
int n, m;
struct Edge{
    int u, v, w;
    bool operator<(Edge y) const{
        return w < y.w;
    }
}p[1005];
int fa[NR];
int fd(int k){
    if (k == fa[k]) return k;
    return fa[k] = fd(fa[k]);
}
int a[NR][NR], du[NR];
int dj[NR], cur, rp[NR];
int ans = 1;
ld lap[NR][NR];
int seq[NR], tail = 0;
int gauss(){
    int ret = 1;
    rep(i, 1, tail - 1){
        int id = i;
        rep(j, i + 1, tail - 1){
            if (abs(lap[j][i]) > abs(lap[id][i])){
                id = j;
            }
        }
        if (id != i){
            swap(lap[id], lap[i]);
            ret *= -1;
        }
        rep(j, i + 1, tail - 1){
            ld tmp = lap[j][i];
            rep(k, 1, tail - 1){
                lap[j][k] -= tmp / lap[i][i] * lap[i][k];
            }
        }
    }
    return ret;
}
void sol(int L, int R){
    //cout << '#' << L << ' ' << R << endl;
    rep(i, 1, n){
        du[i] = 0;
        rep(j, 1, n){
            a[i][j] = 0;
            lap[i][j] = 0;
        }
    }
    cur = 0;
    rep(i, 1, n){
        dj[++cur] = fd(i);
        rp[i] = fd(i);
    }
    sort(dj + 1, dj + cur + 1);
    cur = unique(dj + 1, dj + cur + 1) - dj - 1;
    rep(i, L, R){
        int u = p[i].u, v = p[i].v;
        if (fd(u) != fd(v)){
            fa[fd(u)] = fd(v);
        }
        u = rp[u], v = rp[v];
        a[u][v]++, a[v][u]++, du[u]++, du[v]++;
    }
    rep(dby, 1, n){
        tail = 0;
        rep(i, 1, cur){
            if (fd(dj[i]) == dby){
                seq[++tail] = dj[i];
            }
        }
        if (tail == 0 || tail == 1) continue;
        rep(i, 1, tail) rep(j, 1, tail){
            int aa = 0, dd = 0;
            if (i == j){
                aa = 0;
                dd = du[seq[i]];
            }else{
                aa = a[seq[i]][seq[j]];
                dd = 0;
            }
            lap[i][j] = 1.0 * dd - 1.0 * aa;
        }
        /*
        rep(i, 1, tail - 1){
            rep(j, 1, tail - 1)
                cout << lap[i][j] << ' ';
            cout << endl;
        }
        */
        ld rere = 1.0 * gauss();
        rep(i, 1, tail - 1){
            rere *= lap[i][i];
        }
        int re = ((int)((__int128)(round(rere)) % MOD) + MOD) % MOD;
        /*
        cout << "after: " << endl;
        rep(i, 1, tail - 1){
            rep(j, 1, tail - 1)
                cout << lap[i][j] << ' ';
            cout << endl;
        }
        //cout << ">>>" << re << endl;
        */
        ans = 1ll * ans * re % MOD;
    }
}
signed main(){
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    cin >> n >> m;
    rep(i, 1, n){
        fa[i] = i;
    }
    rep(i, 1, m){
        cin >> p[i].u >> p[i].v >> p[i].w;
    }
    sort(p + 1, p + m + 1);
    int L = 1;
    rep(i, 1, m){
        if (p[i].w != p[L].w){
            sol(L, i - 1);
            L = i;
        }
    }
    sol(L, m);
    rep(i, 1, n){
        if (fd(i) != fd(1)){
            cout << 0 << endl;
            return 0;
        }
    }
    cout << ans << endl;
    return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...