您的位置:首页 > 运维架构

poj 2186 Popular Cows(SCC缩点)

2015-06-27 09:51 323 查看
题目

一开始想到的是求出强连通,进行缩点后,统计入度为强连通个数-1的点,然后累加其中的点个数。

发现下面这组测试数据无法通过。如果仍采用这种做法的话还需要进行拓扑排序??

5 5

1 2

2 3

3 1

1 4

4 5

更简单的方法是统计出度为0的点。如果个数为1,则答案就是该点所包含的点个数;否则为0(多于1个说明不连通)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<stack>
using namespace std;
#define N 100005
vector<int> G
;
int pre
,low
,sccno
,dfs_clock,scc_cnt,cnt
;
stack<int>S;
void dfs(int u){
    pre[u]=low[u]=++dfs_clock;
    S.push(u);
    for(int i=0;i<G[u].size();++i){
        int v=G[u][i];
        if(!pre[v]){
            dfs(v);
            low[u]=min(low[u],low[v]);
        }else if(!sccno[v])
            low[u]=min(low[u],pre[v]);
    }
    if(low[u]==pre[u]){
        cnt[++scc_cnt]=0;
        for(;;){
            int x=S.top();S.pop();
            sccno[x]=scc_cnt;
            ++cnt[scc_cnt];
            if(x==u) break;
        }
    }
}
void find_scc(int n){
    dfs_clock=scc_cnt=0;
    memset(sccno,0,sizeof(sccno));
    memset(pre,0,sizeof(pre));
    for(int i=0;i<n;++i) if(!pre[i]) dfs(i);
}

int out
;
int main()
{
    int n,m,i,x,y,j;
    while(~scanf("%d%d",&n,&m)){
        for(i=0;i<n;++i) G[i].clear();
        while(m--){
            scanf("%d%d",&x,&y);
            G[--x].push_back(--y);
        }
        find_scc(n);
        int ans=0,tot=0;
        for(i=1;i<=scc_cnt;++i)out[i]=0;
        for(i=0;i<n;++i)
            for(j=0;j<G[i].size();++j){
                int v=G[i][j];
                if(sccno[v]!=sccno[i]) ++out[sccno[i]];
            }
        for(i=1;i<=scc_cnt;++i)
            if(!out[i]) {++tot;ans+=cnt[i];}
        printf("%d\n",tot==1?ans:0);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: