poj3352-Road Construction

来源:互联网 发布:淘宝网电子商务模式 编辑:程序博客网 时间:2024/06/06 10:00

无向图双连通分量

昨天刚复习了一波割顶和桥,tarjin相关,今天就写了一道233

算是比较简单的题

大概直接将目前图中所以边-双连通都缩为一个点,然后得到一颗树

设这颗树上所有出度为1的点的个数为sum

容易证明答案为(sum+1)/2

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<string>#include<map>#include<algorithm>using namespace std;int n,r;int to[2005],head[1005],_next[2005];int e[1005][1005],Sta[1005],End[1005],que[1005];int nam[1005],fa[1005];int kp[1005];int cnt=0;int sum,ans=0,tot=0,tnt=0;int sign;void add(int x,int y){     cnt++;     to[cnt]=y;     _next[cnt]=head[x];     head[x]=cnt;}void lcr(int x){     int i,j,k,l;     cnt++;     Sta[x]=End[x]=cnt;     tot++;     que[tot]=x;     for(i=head[x];i;i=_next[i]){         if(to[i]==fa[x])continue;         if(Sta[to[i]]==0){            fa[to[i]]=x;            lcr(to[i]);            End[x]=min(End[to[i]],End[x]);            }         else if(!nam[to[i]])End[x]=min(End[x],Sta[to[i]]);         }     if(Sta[x]==End[x]){        tnt++;        k=que[tot];        while(k!=x){             tot--;             nam[k]=tnt;             k=que[tot];             }        nam[k]=tnt;        tot--;        }}int main(){    int i,j,k,l,x,y;    scanf("%d%d",&n,&r);    for(i=1;i<=r;i++){        scanf("%d%d",&x,&y);        add(x,y);        add(y,x);        }     cnt=0;     lcr(1);     for(i=1;i<=n;i++)         for(j=head[i];j;j=_next[j]){             if((!e[nam[i]][nam[to[j]]])&&nam[i]!=nam[to[j]]){                e[nam[i]][nam[to[j]]]=1;                e[nam[to[j]]][nam[i]]=1;                kp[nam[i]]++;                kp[nam[to[j]]]++;                }             }     for(i=1;i<=tnt;i++)if(kp[i]==1)ans++;     ans=(ans+1)/2;     printf("%d",ans);     return 0;}   


0 0