hdu3394 Railway

题目大意 给一个无向图 判断有多少条割边和多少个冲突边

一个边为冲突边,说明该边所属的双连通分量中存在两个或者两个以上的环。即如果某双连通分量中存在两个以上的环,该双连通分量上的边全部是冲突边。

割边很好求,现在问题就在于冲突边的处理。

后来发现“双连通分量中存在两个以上的环”的条件 可以翻译成“双连通分量中边数大于点数”(参考https://blog.csdn.net/u014141559/article/details/45371373)

而求双连通分量的板子里面我们用栈存边,每次找到双连通分量后栈弹出的所以边就是双连通分量的边数。

再统计点数,只有当边数>点数的时候 ans+=sum_edge

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=10010;
struct Edge
{
    int u,v;
    Edge(){}
    Edge(int u,int v):u(u),v(v){}
}s[100010];
int M,N,dfn[maxn],low[maxn],cnt=0,ans1=0,ans2=0,Index=0,belong[maxn],cnt_bcc=0;
vector<int> edges[maxn];
void addedge(int u,int v)
{
    edges[u].push_back(v);
    edges[v].push_back(u);
}
void tarjan(int u,int fa)
{
    dfn[u]=low[u]=++cnt;
    for(int i=0;i<edges[u].size();i++)
    {
        int v=edges[u][i];
        if(!dfn[v])
        {
            s[++Index]=Edge(u,v);
            tarjan(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                if(low[v]>dfn[u]) ans1++;
                int sum_edge=0,sum_node=0;
                cnt_bcc++;
                for(Edge e;;)
                {
                    e=s[Index--];
                    sum_edge++;
                    if(belong[e.u]!=cnt_bcc){belong[e.u]=cnt_bcc;sum_node++;}
                    if(belong[e.v]!=cnt_bcc){belong[e.v]=cnt_bcc;sum_node++;}
                    if(e.u==u&&e.v==v) break;
                }
                if(sum_node<sum_edge) ans2+=sum_edge;
            }
        }
        else if(dfn[v]<dfn[u]&&fa!=v)
        {
            s[++Index]=Edge(u,v);
            low[u]=min(low[u],dfn[v]);
        }
    }
}
void init()
{
    for(int i=1;i<=N;i++)
        edges[i].clear();
    memset(dfn,0,sizeof dfn);
    memset(belong,0,sizeof belong);
    cnt=0;cnt_bcc=0;ans1=ans2=0;
}
int main()
{
    while(true)
    {
        scanf("%d%d",&N,&M);
        if(N==0&&M==0) break;
        init();
        for(int i=1;i<=M;i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            addedge(u+1,v+1);
        }
        for(int i=1;i<=N;i++)
            if(!dfn[i]) tarjan(i,0);
        printf("%d %d\n",ans1,ans2);
    }
}

有个坑,就是边从0-(N-1) 为此tle了好几次(为什么不是wa)

猜你喜欢

转载自www.cnblogs.com/tmzengbi/p/11769573.html
hdu