题解:P13548 [OOI 2022] Air Reform

· · 题解

boruvka 直接做可以做到 O(n\log^2n),发现需要支持删除节点,找下一个,用一个并查集就能 O(n\log n\alpha(n)) 了。

代码:

#include <bits/stdc++.h>
#define ll int
using namespace std;

basic_string<ll> vct[400005];
ll val[400005],f[400005];
vector<array<ll,3>> edg;
ll n,m,tot;

inline ll find(ll a){
    if (f[a]!=a)f[a]=find(f[a]);
    return f[a];
}

ll sz[400005],son[400005],dep[400005],dfn[400005],to[400005],top[400005],ft[400005],T;
void dfs(ll root,ll fa){
    ft[root]=fa;
    dfn[root]=++T;to[T]=root; 
    sz[root]=1;son[root]=0;
    dep[root]=dep[fa]+1;
    for (ll i:vct[root]){
        dfs(i,root);
        sz[root]+=sz[i];
        if (sz[i]>sz[son[root]])son[root]=i;
    }
}

void dfs2(ll root,ll fa,ll tp){
    top[root]=tp;
    if (son[root])dfs2(son[root],root,tp);
    for (ll i:vct[root]){
        if (i!=son[root]){
            dfs2(i,root,i);
        }
    }
}

inline ll lca(ll u,ll v){
    while (top[u]!=top[v]){
        if (dep[top[u]]<dep[top[v]])v=ft[top[v]];
        else u=ft[top[u]];
    }
    return (dep[u]<dep[v]?u:v);
}

ll mi[200005];
pair<ll,ll> miid[200005];
/*
1 0
4 3
1 2 1
2 3 2
4 3 3
*/
ll p[200005];
unordered_map<ll,ll> mp[200005];
vector<ll> pp[200005];

inline ll read(){
    ll x=0;char c=getchar();
    while (!isdigit(c))c=getchar();
    while (isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x;
}

ll f2[400005],f3[400005];
vector<array<ll,3>> redo; 
ll find2(ll a){

    if (f2[a]!=a){
        redo.push_back({1,a,f2[a]});
        return f2[a]=find2(f2[a]);
    }
    return a;
}
ll find3(ll a){
    if (f3[a]!=a){
        redo.push_back({2,a,f3[a]});
        return f3[a]=find3(f3[a]);
    }
    return a;
}

void solve(){
    n=read();m=read();
    edg.clear();
    vector<array<ll,3>> te;
    for (ll i=1;i<=n;i++)mp[i].clear();
    for (ll i=1;i<=m;i++){
        ll u,v,w;
        u=read();v=read();w=read();
        edg.push_back({w,u,v});
        te.push_back({w,u,v});
        mp[v][u]=mp[u][v]=1;
    }
    sort(edg.begin(),edg.end());
    for (ll i=1;i<=n;i++)f[i]=i;
    for (ll i=1;i<=tot;i++)vct[i].clear();
    tot=n;
    for (ll i=0;i<edg.size();i++){
        ll w=edg[i][0],u=edg[i][1],v=edg[i][2];
        ll x=find(u),y=find(v);
        if (x==y)continue;
        ++tot;
        f[tot]=tot;
        f[x]=tot;
        f[y]=tot;
        vct[tot].push_back(x);
        vct[tot].push_back(y);
        val[tot]=w;
    }
    T=0;
    dfs(tot,0);
    dfs2(tot,0,tot);
    ll c=n;
    for (ll i=1;i<=n;i++)f[i]=i;
    vector<array<ll,3>> e2;
    ll rd=0;
    while (c>1){
        for (ll i=1;i<=n;i++)pp[i].clear();
        for (ll i=1;i<=n;i++){
            mi[i]=1e9;
            miid[i]={0,0};
            pp[find(i)].push_back(i);
        }
        for (ll i=0;i<=tot+1;i++)f2[i]=f3[i]=i;
        for (ll i=1;i<=tot;i++){
            if (to[i]<=n)continue;
            f2[find2(i)]=find2(i-1);
            f3[find3(i)]=find3(i+1);
        }
        for (ll i=1;i<=n;i++){
            if (pp[i].empty())continue;
            redo.clear();
            for (ll j:pp[i]){
                ll x=find2(dfn[j]),y=find2(dfn[j]-1);
                redo.push_back({1,x,f2[x]});
                f2[x]=y;
                x=find3(dfn[j]),y=find3(dfn[j]+1);
                redo.push_back({2,x,f3[x]});
                f3[x]=y;
            }
            ll c=i;
            ll tt=0; 
            for (ll j:pp[i]){
                ll ps=find3(dfn[j]),ps2=find2(dfn[j]);
                ll x=-1,y=-1;
                while (ps<=tot){
                    ll u=to[ps];
                    if (mp[j].count(u)){
                        ps=find3(ps+1);
                    }else{
                        x=to[ps];
                        break;
                    }
                }
                while (ps2>0){
                    ll u=to[ps2];
                    if (mp[j].count(u)){
                        ps2=find2(ps2-1);
                    }else{
                        y=to[ps2];
                        break;
                    }
                }
//                cout<<"?"<< j<<":"<< x<<","<<y<<"\n";
                ll mi2=1e9,mi3=0;
                if (x!=-1){
                    ll w=val[lca(x,j)];
                    if (w<mi2)mi2=w,mi3=x;
                }
                if (y!=-1){
                    ll w=val[lca(y,j)];
                    if (w<mi2)mi2=w,mi3=y;
                }
                if (mi2<mi[c]){
                    mi[c]=mi2,miid[c]={j,mi3};
                }
                //cout<< p[k]<<":"<< mi2<<" "<<mi3<<"\n";
            }
            reverse(redo.begin(),redo.end()); 
            for (auto j:redo){
                if (j[0]==1)f2[j[1]]=j[2];
                else f3[j[1]]=j[2];
            }
        }
        for (ll i=1;i<=n;i++){
            if (!miid[i].first)continue;
            ll u=find(miid[i].first),v=find(miid[i].second);
            if (u!=v){
                e2.push_back({mi[i],miid[i].first,miid[i].second});
                f[u]=v;
                c--;
            }
        }
    }
    sort(e2.begin(),e2.end());
    for (ll i=1;i<=n;i++)f[i]=i;
    for (ll i=1;i<=tot;i++)vct[i].clear();
    tot=n;
    for (ll i=0;i<e2.size();i++){
        ll w=e2[i][0],u=e2[i][1],v=e2[i][2];
        ll x=find(u),y=find(v);
        if (x==y)continue;
        ++tot;
        f[tot]=tot;
        f[x]=tot;
        f[y]=tot;
        vct[tot].push_back(x);
        vct[tot].push_back(y);
        val[tot]=w;
    }
    T=0;
    dfs(tot,0);
    dfs2(tot,0,tot);
    for (auto i:te){
        cout<< val[lca(i[1],i[2])]<<" ";
    }
    cout<<"\n";
}

int main(){
    cin.tie(0);cout.tie(0);
    ios::sync_with_stdio(false);
    ll t,g;
    t=read();g=read();
    while(t--)solve();
    return 0;
}