UVA-10765 Doves and bombs (双连通分量)

题目大意:给一个n个点的无向连通图,找出删除某个点后的连通块个数。

题目分析:统计一下每个节点属于几个双连通分量,若是割点,得到的便是答案,否则答案为1。

 

代码如下:

 

# include<iostream>
# include<cstdio>
# include<stack>
# include<vector>
# include<cstring>
# include<algorithm>
using namespace std;
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a));

const int N=10005;
struct Edge
{
    int u,v;
    Edge(int _u,int _v):u(_u),v(_v){}
    bool operator < (const Edge &a) const {
        if(v==a.v)  return u<a.u;
        return v>a.v;
    }
};
stack<Edge>S;
vector<Edge>ans;
vector<int>G[N],bcc[N];
int n,m,dfs_cnt,bcc_cnt,bccno[N],pre[N],low[N],cnt[N],iscut[N];

void dfs(int u,int fa)
{
    low[u]=pre[u]=++dfs_cnt;
    int child=0;
    REP(i,0,G[u].size()){
        int v=G[u][i];
        if(pre[v]==0){
            ++child;
            S.push(Edge(u,v));
            dfs(v,u);
            low[u]=min(low[u],low[v]);
            if(low[v]>=pre[u]){
                iscut[u]=1;
                bcc[++bcc_cnt].clear();
                while(1){
                    Edge x=S.top();
                    S.pop();
                    if(bccno[x.u]!=bcc_cnt){
                        bcc[bcc_cnt].push_back(x.u);
                        bccno[x.u]=bcc_cnt;
                    }if(bccno[x.v]!=bcc_cnt){
                        bcc[bcc_cnt].push_back(x.v);
                        bccno[x.v]=bcc_cnt;
                    }
                    if(x.u==u&&x.v==v) break;
                }
            }
        }else if(pre[v]<pre[u]&&v!=fa){
            S.push(Edge(u,v));
            low[u]=min(low[u],pre[v]);
        }
    }
    if(fa<0&&child==1) iscut[u]=0;
}

void findBcc()
{
    CL(bccno,0);
    CL(iscut,0);
    CL(pre,0);
    dfs_cnt=bcc_cnt=0;
    REP(i,0,n) if(!pre[i])
        dfs(i,-1);
}

int main()
{
    int a,b;
    while(scanf("%d%d",&n,&m)&&(n+m))
    {
        REP(i,0,n) G[i].clear();
        while(scanf("%d%d",&a,&b))
        {
            if(a==-1&&b==-1)
                break;
            G[a].push_back(b);
            G[b].push_back(a);
        }
        findBcc();
        ans.clear();
        CL(cnt,0);
        REP(i,1,bcc_cnt+1) REP(j,0,bcc[i].size()) ++cnt[bcc[i][j]];
        REP(i,0,n){
            if(iscut[i])
                ans.push_back(Edge(i,cnt[i]));
            else
                ans.push_back(Edge(i,1));
        }
        sort(ans.begin(),ans.end());
        REP(i,0,m) printf("%d %d\n",ans[i].u,ans[i].v);
        printf("\n");
    }
    return 0;
}

  

posted @ 2015-10-30 14:14  20143605  阅读(421)  评论(0编辑  收藏  举报