HDU -- 3394 Railway ( 双连通 求块判断环)

来源:互联网 发布:js页面跳转动画效果 编辑:程序博客网 时间:2024/05/17 23:08

题目大意:公园有n个景点,公园的管理员要计划修建m条能形成环形的观光路径。此时,如果一条路径没有被任何一个环路所使用,它就是不需要的边,多余边;如果一个路径被多余一个环路所使用,那它就是冲突边;求多余边和冲突边的个数。

思路分析:

①:多余边:即是双连通的割边;

②:冲突边:把图分成多个块,求块里的边数,如果块里的边数大于点数,就说明这个块里的边都是冲突边;如何理解呢,如果一个块中的边多余点数,就说明有边把最外边的大环分割成了几个小环,那么小环和小环之间,小环和大环之间就会形成公用边,进而块里的环也就都是冲突边了。

代码实现:

#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<stack>#include<cmath>#include<algorithm>#include<iostream>//#pragma comment(linker, "/STACK:102400000,102400000")#define Min(a,b) ((a)<(b)?(a):(b))#define Max(a,b) ((a)>(b)?(a):(b))#define MEM(a) (memset((a),0,sizeof(a)))#define MEME(a) (memset((a),-1,sizeof(a)))#define MEMX(a) (memset((a),0x3f,sizeof(a)))using namespace std;const int N=10005;const int M=100005;int dfn[N],low[N],vis[N],block[N],st[N],bccn,top,s_top,tim,ans1,ans2,cnt,n,m;bool in[N];struct Edge{    int v;    Edge *next;}*head[N],e[M*2];void Addedge(int from,int to){    Edge *p=&e[top++];    p->v=to;    p->next=head[from];    head[from]=p;}void Find_edge(){    int sum=0,u,v;    for(int i=1;i<=cnt;++i){        u=block[i];        for(Edge *p=head[u];p;p=p->next){            if(in[p->v]) sum++;        }    }    sum/=2;    if(sum>cnt) ans2+=sum;}void Tarjan_bcc(int u,int fa){    dfn[u]=low[u]=++tim;    st[++s_top]=u;    int v,tmp;    for(Edge *p=head[u];p;p=p->next){        v=p->v;        if(v==fa) continue;        if(!dfn[v]){            Tarjan_bcc(v,u);            low[u]=Min(low[u],low[v]);            if(low[v]>dfn[u]) ans1++;            if(low[v]>=dfn[u]){                cnt=0;                memset(in,0,sizeof(in));                do{                    tmp=st[s_top--];                    block[++cnt]=tmp;                    in[tmp]=1;                }while(tmp!=v);                block[++cnt]=u;                in[u]=1;                Find_edge();            }        }else low[u]=Min(low[u],dfn[v]);    }}int main(){    int a,b;    while(~scanf("%d%d",&n,&m),(n||m)){        MEM(head),MEM(dfn),MEM(low),MEM(block),MEM(in);        bccn=top=s_top=ans1=ans2=tim=0;        for(int i=1;i<=m;++i){            scanf("%d%d",&a,&b);            Addedge(a,b);            Addedge(b,a);        }        for(int i=0;i<n;++i) if(!dfn[i]) Tarjan_bcc(i,-1);        printf("%d %d\n",ans1,ans2);    }}


0 0
原创粉丝点击