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 ;
}

  

posted @ 2012-08-11 11:28  快乐.  阅读(146)  评论(0编辑  收藏  举报