bzoj 2730 HNOI2012 矿场搭建 tarjan

tarjan求割点,

每个点双如果不连割点,内部应建两个,连着一个割点,应建一个,连着多个,不用建

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 1500
using namespace std;
int n,m,cnt,num,tot,ans1,cosmos,bo[N];
long long ans2;
int dfn[N],low[N],judge[N],top,son,root;
int e=1,head[N];
struct edge{
    int u,v,next;
}ed[5000];
void add(int u,int v){
    ed[e].u=u; ed[e].v=v;
    ed[e].next=head[u]; head[u]=e++;
}
void tarjan(int x,int f){
    dfn[x]=low[x]=++top;
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(v==x) continue;
        if(!dfn[v]){
            tarjan(v,x);
            low[x]=min(low[x],low[v]);
        }
        else{low[x]=min(low[x],dfn[v]);continue;}
        if(dfn[x]<=low[v]){
            if(x==root)son++;
            else judge[x]=1;
        }
    }
}
void dfs(int x){
    bo[x]=tot;
    if(judge[x]) return;cnt++;
    for(int i=head[x];i;i=ed[i].next){
        int v=ed[i].v;
        if(judge[v]&&bo[v]!=tot){num++;bo[v]=tot;}
        if(!bo[v])dfs(v);
    }
}
void init(){
    memset(dfn,0,sizeof dfn);
    memset(low,0,sizeof low);
    memset(judge,0,sizeof judge);
    memset(bo,0,sizeof bo); cosmos++;
    n=0; ans1=0; ans2=1; tot=0; top=0;
    e=1; memset(head,0,sizeof head);
}
int main(){
    while(scanf("%d",&m)==1&&m!=0){
        init();
        int u,v;
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u,&v);
            n=max(n,max(u,v));
            add(u,v); add(v,u);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i]){
                son=0; root=i; 
                tarjan(i,0);
                if(son>1) judge[i]=1;
            }
        }
        /*for(int i=1;i<=n;i++)
            printf("%d  %d\n",i,judge[i]);*/
        for(int i=1;i<=n;i++){
            if(!bo[i]&&!judge[i]){
                tot++;cnt=num=0;
                dfs(i);
                if(!num){ans1+=2;ans2*=cnt*(cnt-1)/2;}
                if(num==1){ans1++;ans2*=cnt;}
                //printf("%d  %d  %d  %d\n",i,tot,cnt,num);
            }
        }
        printf("Case %d: %d %lld\n",cosmos,ans1,ans2);
    }
    return 0;
}


posted @ 2017-08-10 21:48  Ren_Ivan  阅读(116)  评论(0编辑  收藏  举报