HDU 3394 Railway 块
http://acm.hdu.edu.cn/showproblem.php?pid=3394
求有几个边不在环中,有几个边在不同的环中
代码:
//块没有割点的连通子图 #include<iostream> #include<cstdio> #include<string> #include<cstring> #define Min(a,b)a<b?a:b #define nMAX 10002 #define mMAX 20002 using namespace std; int head[nMAX],dfn[nMAX],low[nMAX],stack[nMAX],num[nMAX];//de_sta[nMAX];//栈中点的个数 int s_edge,n,top,times; int zero,one,two; int atype,belon[nMAX]; bool vs[nMAX]; struct { int to,next; }edge[mMAX]; void addedge(int u,int v) { s_edge++; edge[s_edge].to=v; edge[s_edge].next=head[u]; head[u]=s_edge; } void check(int s) { int i,j,k=0; memset(vs,0,sizeof(vs)); for(i=1;i<=s;i++) vs[num[i]]=1; for(i=1;i<=s;i++) { for(int e=head[num[i]];e;e=edge[e].next) { int v=edge[e].to; if(vs[v])k++; } } k/=2; if(k==s)one+=k; else if(k>s)two+=k; // else zero+=k; } void tarjan(int u,int fa) { dfn[u]=++times; low[u]=times; stack[++top]=u; int e; for(e=head[u];e;e=edge[e].next) { int v=edge[e].to; if(v==fa)continue; if(!dfn[v]) { cout<<"u,v="<<u<<" "<<v<<endl; tarjan(v,u); low[u]=Min(low[u],low[v]); int j; int cnt; if(dfn[u]<=low[v])//u是割点 { atype++; cnt=0; do { j=stack[top--]; belon[j]=atype; num[++cnt]=j; vs[j]=1; }while(j!=v); num[++cnt]=u;//割点属于多个块 belon[u]=atype; // vs[u]=1; check(cnt); } } else low[u]=Min(low[u],dfn[v]);//加不加(v!=fa)均可,因为u是割点 } return ; } void init() { atype=0; s_edge=0; top=0; times=0; memset(head,0,sizeof(head)); memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); return ; } int main() { int m,u,v,i; while(~scanf("%d%d",&n,&m)) { if(n==0&&m==0)break; init(); while(m--) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } zero=one=two=0; for(i=0;i<n;i++) if(!dfn[i]) tarjan(i,-1); zero=s_edge/2-two-one; // for(i=0;i<n;i++) // cout<<"low["<<i<<"]="<<low[i]<<endl; printf("%d %d\n",zero,two); } return 0 ; }