首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网络技术 > 网络基础 >

[点双接通分量]hdoj 3394:Railway

2012-08-26 
[点双连通分量]hdoj 3394:Railway大致题意:? ? 给出一个无向图,求出割边的条数,并求出存在在多个环中的边

[点双连通分量]hdoj 3394:Railway

大致题意:
? ? 给出一个无向图,求出割边的条数,并求出存在在多个环中的边的条数。

?

大致思路:

? ? 先给出题人跪了,真的没想明白为什么circuit是点双连通分量的意思,用边双连通分量wa了一上午。知道了是点双连通分量,问题就简单了,如果一个circuit中的点数小于边数,那么这个分量中所有的边肯定是多余的。

?

#include<iostream>#include<cstdio>#include <algorithm>#include<cstring>using namespace std;const int inf=1<<30;const int nMax=30015;const int mMax=500000;class edge{public:    int u,v,nex;};edge e[mMax];int k,k1,head[nMax];int dfn[nMax],low[nMax],sta[nMax],top,atype,belon[nMax],dep;  bool insta[nMax];int n,m;int ans,vis[nMax],num[nMax],cnt,sum;void addedge(int a,int b){    e[k].u=a;    e[k].v=b;    e[k].nex=head[a];    head[a]=k;k++;}void getcont(){    int i,j,a=0,b;    memset(vis,0,sizeof(vis));    for(i=1;i<=cnt;i++)    {        vis[num[i]]=1;    }    for(i=1;i<k;i++)    {        if(vis[e[i].u]&&vis[e[i].v])        {            a++;        }    }    a/=2;   // cout<<cnt<<"wada"<<a<<endl;    if(a>=cnt)sum+=a;  //这里略有想不明白,写上之后水过去了。以后再研究    if(a>cnt){        ans+=a;    }}void Tarjan(int u,int rt){                 //我的Tarjan模版    int i,t;    dfn[u]=low[u]=++dep;    sta[++top]=u;    insta[u]=1;    for(i=head[u];i;i=e[i].nex){        int v=e[i].v;        if(v==rt)continue;        if(!dfn[v]){            Tarjan(v,u);            low[u]=min(low[u],low[v]);            if(dfn[u]<=low[v]){     ///要注意一个点可能同时属于不同的点双连通分量                cnt=0;                do{                    t=sta[top--];                    insta[t]=0;                    num[++cnt]=t;                }while(v!=t);                num[++cnt]=u;                getcont();            }        }        else{            if(insta[v])low[u]=min(low[u],dfn[v]);        }    }}void init(){    k=1;    dep=1;    top=atype=0;    memset(insta,0,sizeof(insta)); //是否在栈中    memset(head,0,sizeof(head));   //静态链表头指针    memset(low,0,sizeof(low));     //Tarjan的low数组    memset(dfn,0,sizeof(dfn));     //Tarjan的dfn数组    memset(belon,0,sizeof(belon)); //记录每个点属于哪一个双连通分量}int main(){    int i,j,a,b;    while(scanf("%d%d",&n,&m)!=EOF&&(n||m)){        init();        ans=sum=0;        for(i=0;i<m;i++){            scanf("%d%d",&a,&b);            a++,b++;            addedge(a,b);            addedge(b,a);        }circuit        for(i=1;i<=n;i++)        {            if(!dfn[i])            {                Tarjan(i,-1);            }        }        a=m-sum;        printf("%d %d\n",a,ans);    }    return 0;}
?

热点排行