hdu 3394 Railway 点双连通分量 + 桥

2017-08-07  本文已影响0人  Gitfan

hdu 3394 Railway
双连通分量

题意:给一个无向图。如果至少有两个环共用了一些边,那么这些边被认为是“冲突边”。如果一些边不在任何一个环中,这些边被认为是“多余边”。你要找出这个图中有多少“多余边”和“冲突边”然后输出条数。另外这图不一定是连通的

1.“多余边”不在任何一个环中,那么多余边一定是桥,所以统计这个无向图中有多少桥即可

2.“冲突边”有多少,这个有点费劲,但是不难想到。如果一个环比较特殊,n个点刚好n条边,例如(1,2)(2,3)(1,3)这种环,这个环内,一条“冲突边”都没有,但是如果一个环内的边数大于点数,那么这个环内所有边都是“冲突边”(真可惜,因为有多出来的那些边后,相当于把最外面的大环分割成了内部的几个小环,这些小环和小环之间,小环和大环之间一定会公用一些边,这些边就是“冲突边”,而且可以发现,所有边都会被公用,太可惜了......),例如sample里面的(5,6)(5,4)(6,7)(4,7)(5,7),相当于最外面的大环<6,5,4,7,6> , 而里面的边(5,7)把这个大环分割成了两个小环。因为是求环,所以求的是点双连通分量。

所以做法就是,求出这个无向图有多少个点双连通分量,对于每个点双连通分量,如果内部的边数>点数,那么这些边全部都是冲突边

#include <cstdio>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int MAXN=10010;
const int MAXE=200010;
struct Node
{
    int to,next,cut;
};
Node edge[MAXE];
int cnt,head[MAXN];
void addEdge(int u,int v)
{
    edge[cnt].to=v;
    edge[cnt].cut=0;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
struct Edge
{
    int u,v;
    Edge(){}
    Edge(int u,int v):u(u),v(v){}
};
stack<Edge> coolector;
int low[MAXN],dfn[MAXN],clocks;
int isCut[MAXN],bccno[MAXN],bcc_cnt;
vector<int> bcc[MAXN];
vector<Edge> edgeCnt[MAXN];
int bridges;
void DFS(int u,int e)
{
    low[u]=dfn[u]=++clocks;
    int child=0;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        if(e==(i^1)) continue;
        int v=edge[i].to;
        Edge e(u,v);
        if(dfn[v]==0)
        {
            coolector.push(e);
            child++;
            DFS(v,i);
            low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                isCut[u]=true;
                bcc_cnt++;
                bcc[bcc_cnt].clear();
                edgeCnt[bcc_cnt].clear();
                while(true)
                {
                    Edge tmp=coolector.top();
                    coolector.pop();
                    edgeCnt[bcc_cnt].push_back(tmp);
                    if(bccno[tmp.u]!=bcc_cnt) {bccno[tmp.u]=bcc_cnt;bcc[bcc_cnt].push_back(tmp.u);}
                    if(bccno[tmp.v]!=bcc_cnt) {bccno[tmp.v]=bcc_cnt;bcc[bcc_cnt].push_back(tmp.v);}
                    if(tmp.u==u&&tmp.v==v) break;
                }
            }
            if(low[v]>dfn[u])
            {
                edge[i].cut=1;
                edge[i^1].cut=1;
                bridges++;
            }
        }
        else if(dfn[v]<dfn[u])
        {
            coolector.push(e);
            low[u]=min(low[u],dfn[v]);
        }
    }
    if(e<0&&child==1) isCut[u]=0;
}
void find_cc(int n)
{
    memset(isCut,0,sizeof(isCut));
    memset(bccno,0,sizeof(bccno));
    memset(dfn,0,sizeof(dfn));
    clocks=bcc_cnt=bridges=0;
    for(int i=0;i<n;i++)
    {
        if(dfn[i]==0)
        {
            DFS(i,-1);
        }
    }
}
void work(int n)
{
    find_cc(n);
    int edges=0;
    for(int i=1;i<=bcc_cnt;i++)
    {
        if(edgeCnt[i].size()>bcc[i].size())
        {
            edges+=edgeCnt[i].size();
        }
    }
    printf("%d %d\n",bridges,edges);
}
int main()
{
    int n,m,a,b;
    while(scanf("%d%d",&n,&m)!=EOF,n+m)
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a,&b);
            addEdge(a,b);
            addEdge(b,a);
        }
        work(n);
    }
}
上一篇下一篇

猜你喜欢

热点阅读