zoukankan      html  css  js  c++  java
  • Luogu5234[JSOI2012]越狱老虎桥

    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
    ",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
    ",ed[i].w); return 0;
            }
        }
        printf("-1
    ");
        return 0;
    }
    
    
    
  • 相关阅读:
    一天一个shell实例(1)文本中n个出现频率最高的单词(转)
    JNDI全攻略(一)(转)
    JNDI 学习(转)
    JNDI全攻略(二)(转)
    C#开发系列 文章索引
    AppControls
    JSF系列 文章索引
    [转载]DELPHI组件安装全攻略
    什么是有价值的人生
    [转载]InnoSetup5.2.3啊风增强版 安装代码
  • 原文地址:https://www.cnblogs.com/pkh68/p/10533884.html
Copyright © 2011-2022 走看看