某岛

… : "…アッカリ~ン . .. . " .. .
July 5, 2022

Luogu P4412. [SHOI2004]最小生成树

这个题主要麻烦的点还是找环。。。


const int N = 50 + 9, M = int(1.5e3) + 9;

struct Graph {
    int id[N][N];

    struct edge {
        int x, y, w;
        void in() {
            RD(x, y, w);
        }
    } E[M];

    int n, m;

    void in() {
        RD(n, m); REP_1(i, m) {
            E[i].in();
            id[E[i].x][E[i].y] = id[E[i].y][E[i].x] = i;
        }
    }
} G;

struct Tree {
    VI adj[N]; int fa[N], dep[N];

    void dfs(int u = 1, int p = -1) {
        for (auto v: adj[u]) if (v != p) {
            fa[v] = u; dep[v] = dep[u] + 1;
            dfs(v, u);
        }
    }

    void in() {
        DO(G.n-1) {
            int x, y; RD(x, y);
            adj[x].PB(y);
            adj[y].PB(x);
        }
        dfs();
    }
} T;

struct Simplex {
    const static int N = ::M, M = int(1e3) + 9;
    DB a[N+1][M+1];
    int n, m;

    void pivot(int in, int out) {
        REP(i, m+1) if(i!=in) a[out][i] /= -a[out][in]; //重置out约束
        a[out][in] = 1/a[out][in];

        REP(i, n+1) if (i!=out && sgn(a[i][in])) { //重新计算其他约束
            DB t = a[i][in]; a[i][in] = 0;
            REP(j, m+1) a[i][j] += t*a[out][j];
        }
    }

    DB run() {
        while (true) {
            int in=0, out=0; DB Min=OO;
            REP_1(i, m) if(sgn(a[0][i])>0) {
                in=i;
                break;
            }
            if(!in)return a[0][0];
            REP_1(i, n) if(sgn(a[i][in])<0&&a[i][0]/-a[i][in]<Min) {
                Min=a[i][0]/-a[i][in];
                out=i;
            }
            if(!out)throw; //unbounded
            pivot(in, out);
        }
    }

    int gao() {

        // z b
        // c A

        G.in(); T.in();
        n = G.m; m = 0; REP_1(i, n) {
            a[i][0] = 1;
            int u = G.E[i].x, v = G.E[i].y;
            if (T.dep[u] < T.dep[v]) swap(u, v);
            if (T.fa[u] != v) { // E[i] is not a tree edge
                while (u != v) {
                    int p = T.fa[u];
                    int j = G.id[p][u]; // E[j] is a tree edge
                    if (G.E[i].w < G.E[j].w) {
                        ++m; a[i][m] = a[j][m] = -1;
                        a[0][m] = G.E[j].w - G.E[i].w;
                    }
                    u = p; if (T.dep[u] < T.dep[v]) swap(u, v);
                }
            }
        }

        return run();
    }
} fst;


int main() {

#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
#endif
    OT(fst.gao());
}