HDU 4005 The war(割点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4005

题意:给出一个带权无向图。权表示删除该边的代价。现在会新增加一条边之后你可以删除一条边使得图不连通。求最小代价。

思路:首先将图缩点变成树。之后找到树中最小的边(u,v),然后从u,v分别向下DFS,到达一个点S时,S下面的边的次小值可以更新答案。

vector<pair<int,int> > V1[N];

int dfn[N],low[N],visit[N],color[N];

int id,n,m,colorCnt;

stack<int> S;





struct node

{

    int v,w,next;

};



node edges[200005];

int head[N];

int e;



void add(int u,int v,int w)

{

    edges[e].v=v;

    edges[e].w=w;

    edges[e].next=head[u];

    head[u]=e++;

}





void DFS(int u,int pre,int preEdgeId)

{

    low[u]=dfn[u]=++id;

    S.push(u);

    visit[u]=1;

    int i;

    for(i=head[u];i!=-1;i=edges[i].next)

    {

        int v=edges[i].v;



        if(v==pre&&(i^1)==preEdgeId) continue;



        if(!dfn[v])

        {

            DFS(v,u,i);

            upMin(low[u],low[v]);

        }

        else if(visit[v])

        {

            upMin(low[u],dfn[v]);

        }

    }

    if(dfn[u]==low[u])

    {

        colorCnt++;

        int v;

        do

        {

            v=S.top();

            S.pop();

            visit[v]=0;

            color[v]=colorCnt;

        }while(u!=v);

    }

}





int MinEdge,MinEdgeA,MinEdgeB;



void reBuild()

{

    MinEdge=INF;

    int i;

    FOR1(i,colorCnt) V1[i].clear();

    FOR1(i,n)

    {

        int j;

        for(j=head[i];j!=-1;j=edges[j].next)

        {

            int v=edges[j].v;

            int w=edges[j].w;

            if(color[i]!=color[v])

            {

                V1[color[i]].pb(MP(color[v],w));

                if(w<MinEdge)

                {

                    MinEdge=w;

                    MinEdgeA=color[i];

                    MinEdgeB=color[v];

                }

            }

        }

    }

}



void deal()

{

    while(!S.empty()) S.pop();

    clr(visit,0);

    clr(dfn,0);

    int i;

    id=colorCnt=0;

    FOR1(i,n) if(!dfn[i]) DFS(i,-1,-1);

    reBuild();

}



int ans;





int dfs(int u,int pre)

{

    int i;

    int Min1=-1,Min2=-1,Min=INF;

    FOR0(i,SZ(V1[u]))

    {

        int v=V1[u][i].first;

        int w=V1[u][i].second;

        if(v==pre) continue;

        int MM=dfs(v,u);

        if(MM<w) w=MM;

        if(-1==Min1) Min1=w;

        else if(-1==Min2)

        {

            if(w<Min1) Min2=Min1,Min1=w;

            else Min2=w;

        }

        else

        {

            if(w<Min1) Min2=Min1,Min1=w;

            else if(w<Min2) Min2=w;

        }



        if(w<Min) Min=w;



    }

    if(-1!=Min2) upMin(ans,Min2);

    return Min;

}



int main()

{

    Rush(n)

    {

        RD(m);

        int i;

        FOR1(i,n) head[i]=-1;

        e=0;

        FOR1(i,m)

        {

            int u,v,w;

            RD(u,v,w);

            add(u,v,w);

            add(v,u,w);

        }



        deal();

        ans=INF;



        dfs(MinEdgeA,MinEdgeB);

        dfs(MinEdgeB,MinEdgeA);

        if(INF==ans) puts("-1");

        else PR(ans);



    }

}

  

你可能感兴趣的:(HDU)