1. 程式人生 > >Luogu5234[JSOI2012]越獄老虎橋

Luogu5234[JSOI2012]越獄老虎橋

void sort eof ger enable per 邊雙連通分量 mem ems

Luogu5234[JSOI2012]越獄老虎橋

題面:洛谷

解析

題意中的要求即為割掉權值最小的割邊,所以先把圖縮點(這裏應該是邊雙連通分量),現在考慮增加一條邊會對縮點後的樹造成什麽影響,無非是成環,然後環上的邊不能割掉。現在考慮貪心,從小到大加邊,若這些邊在一條鏈上,就繼續,反之輸出答案,用\(lca\)維護即可,註意特判。

代碼


// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define N 500005
#define M 1000005
using namespace std;
int n,m;

#define gc() getchar()
inline int In(){
    char c=gc(); int x=0,ft=1;
    for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1;
    for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0';
    return x*ft;
}
inline int min(int a,int b){
    return a<b?a:b;
}
int h[N],U[M],V[M],W[M],e_tot=1;
struct E{ int to,nex,d; }e[M<<1];
inline void add(int u,int v,int w){
    e[++e_tot]=(E){v,h[u],w}; h[u]=e_tot;
    e[++e_tot]=(E){u,h[v],w}; h[v]=e_tot;
}
int dfs_clock=0,ecc_cnt=0,S_top=0,dfn[N],low[N],S[N],id[N];
void dfs(int u,int pre){
    dfn[u]=low[u]=++dfs_clock; S[++S_top]=u;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; if(v==pre) continue;
        if(!dfn[v]){
            dfs(v,u);
            low[u]=min(low[u],low[v]);
        }
        else low[u]=min(low[u],dfn[v]);
    }
    if(dfn[u]==low[u]){
        ++ecc_cnt; int v;
        do{ v=S[S_top--]; id[v]=ecc_cnt; }while(v!=u);
    }
}
int ec=0;
struct Ed{
    int u,v,w;
    bool operator < (const Ed& rhs) const { return w<rhs.w; }
}ed[N];
int d[N],sz[N],son[N],fa[N],top[N];
void dfs1(int u,int pre,int dep){
    d[u]=dep; fa[u]=pre; sz[u]=1;
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; if(v==fa[u]) continue;
        dfs1(v,u,dep+1); sz[u]+=sz[v];
        if(!son[u]||sz[son[u]]<sz[v]) son[u]=v;
    }
}
void dfs2(int u,int pre){
    top[u]=pre; if(son[u]) dfs2(son[u],pre);
    for(int i=h[u],v;i;i=e[i].nex){
        v=e[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
    }
}
inline int LCA(int x,int y){
    while(top[x]!=top[y]){
        if(d[top[x]]<d[top[y]]) swap(x,y);
        x=fa[top[x]];
    }
    return d[x]>d[y]?y:x;
}
int main(){
    n=In(); m=In();
    for(int i=1;i<=m;++i){
        U[i]=In(); V[i]=In(); W[i]=In();
        add(U[i],V[i],W[i]);
    }
    dfs(1,-1); e_tot=0; memset(h,0,sizeof(h));
    for(int i=1;i<=m;++i){
        U[i]=id[U[i]]; V[i]=id[V[i]];
        if(U[i]!=V[i]){
            add(U[i],V[i],W[i]);
            ed[++ec]=(Ed){U[i],V[i],W[i]};
        }
    }
    dfs1(1,-1,0); dfs2(1,1); sort(ed+1,ed+1+ec);
    int a=ed[1].u,b=ed[1].v,pre=LCA(a,b); if(d[a]>d[b]) swap(a,b);
    for(int i=2,u,v;i<=ec;++i){
        u=ed[i].u; v=ed[i].v; if(d[u]>d[v]) swap(u,v);
        int p1=LCA(u,a),p2=LCA(v,a),p3=LCA(u,b),p4=LCA(v,b);
        if(pre==a){
            if(p1==a&&p2==a&&p3==u&&p4==v) continue;
            if(p3==b&&p4==b){ b=v; continue; }
            if(p1==u&&p2==v){ a=u; pre=a; continue; }
            if(d[p3]<=d[a]){ a=v; continue; }
            printf("%d\n",ed[i].w); return 0;
        }
        else{
            if(p1==a&&p2==a){ a=v; continue; }
            if(p3==b&&p4==b){ b=v; continue; }
            if(d[u]>=d[pre]&&p1==u&&p2==v) continue;
            if(d[u]>=d[pre]&&p3==u&&p4==v) continue;
            printf("%d\n",ed[i].w); return 0;
        }
    }
    printf("-1\n");
    return 0;
}

Luogu5234[JSOI2012]越獄老虎橋