树上倍增

无论如何跟着father更新,如果讨论麻烦请重载,尽管常数有点大
严格次小生成树

#include
using namespace std;
#define int long long
inline char gc()
{
    static const int N = 1<<22;
    static char b[N], *i, *j;
    return i==j&&(j=(i=b)+fread(b,1,N, stdin), i==j)?EOF:*i++;
}
#define is read()
inline int is
{
    int a=0, n=0; char c;
    while(c<'0'||c>'9') c=='-'&&(n=1), c=gc();
    while(c>='0'&&c<='9') a=(a+(a<<2)<<1)+(c&15), c=gc();
    return n?-a:a;
}
const int N = 1e5+5;
const int M = 6e5+5;
int n,m;
int nxt[M], fst[N], to[M], w8[M]; 
void aE(int u, int v, int w)
{
    static int i = 1;
    nxt[++i] = fst[u]; fst[u]=i; to[i]=v; w8[i]=w;
}
struct Magn
{
    int a, b;
    Magn operator + (const Magn & that) const
    {
        int temp[4] = {a,b,that.a, that.b};
        sort(temp, temp+4);
        int m = unique(temp, temp+4) - temp;
        return (Magn){temp[m-1], m>1 ? temp[m-2] : 0};
    }
};
struct Edge
{
    int u, v, w;
    bool operator <(const Edge & that) const
    {
        return w=dep[v])
        {
            ans = ans + meg[u][i];
            u = fa[u][i];
        }
    if(u==v) return ans;
    for(int i=lg; ~i; --i)
    {
        if(fa[u][i]^fa[v][i])
        {
            ans = ans + meg[u][i] + meg[v][i];
            u=fa[u][i]; v=fa[v][i];
        }
    }
    return ans + meg[u][0] + meg[v][0];
    
}
void mul(int u, int ine)
{
    static int temp[4];
    dep[u] = dep[fa[u][0]]+1;
    meg[u][0] = (Magn){ine ? w8[ine] : 0,0};
    for(int i=1; i<=lg; i++)
    {
        fa[u][i] = fa[fa[u][i-1]][i-1];
        meg[u][i] = meg[u][i-1] + meg[fa[u][i-1]][i-1];
    }
    for(int e=fst[u];e;e=nxt[e])
    {
        int v = to[e];
        if(v ^ fa[u][0]) fa[v][0] = u, mul(v, e);
    }
}
int ans = 1e9;
signed main()
{
    freopen("a.in", "r", stdin);
    n=is, m=is; lg = log(n)/log(2)+1;
    int x,y,z;
    for(int i=1; i<=m; i++)
    {
        x=is, y=is, z=is;
        es[++etot] = (Edge){x,y,z};
    }
    sort(es+1, es+1+etot);
    uf.init();
    for(int e=1; e<=m; e++)
    {
        int fu = uf.g(es[e].u), fv = uf.g(es[e].v);
        if(fu ^ fv)
        {
            aE(es[e].u,es[e].v,es[e].w);
            aE(es[e].v,es[e].u,es[e].w);
            uf.f[fu] = fv;
            mstw += es[e].w;
            onmst[e] = 1;
        }
    }
    mul(1, 0);
    for(int e=1; e<=m; e++)
    {
        if(!onmst[e])
        {
            int w = es[e].w;
            Magn macro = lca(es[e].u, es[e].v);
            if(macro.a < w) ans = min(ans, w - macro.a);
            else if(macro.b) ans = min(ans, w - macro.b);
        }
    }
    cout<<(mstw + ans);
}

你可能感兴趣的:(树上倍增)