【图论】[BZOJ 1051]受欢迎的牛

题目问的是有多少个牛收到所有的牛的喜欢,因为这道题目具有传递性,所以在有向图上找出强连通子图,可以发现每个子图中的奶牛一定是互相喜欢的,所以不用考虑这样的情况(把每一个强连通子图找出,缩点)然后整个图就变成了有向无环图,那么同一个点必须受到其他所有奶牛的喜欢,那么它不能喜欢任意的除了自己这个联通子图的牛的其他牛(会形成环)所以统计一下是否存在出度为0的点就好了,但是如果存在两个或两个以上的出度为0的点,那么这个有向无环图就变成了一个森林(多个独立的有向无环图)

#include <cstdio>
#include <algorithm>
#include <iostream>
#include <stack>
using namespace std;
const int MAXN = 10000;
const int MAXM = 50000;
struct node{
    int v;
    node *next;
}Edges[MAXM*2+10], *ecnt=Edges, *adj[MAXN+10];
void addedge(int u, int v){
    ++ecnt;
    ecnt->v = v;
    ecnt->next = adj[u];
    adj[u] = ecnt;
}
int dfn[MAXN+10], low[MAXN+10], dcnt, id[MAXN+10], kcnt, sz[MAXN+10];
bool insta[MAXN+10];
stack<int> sta;
void dfs(int u){
    dfn[u]  = low[u] = ++dcnt; sta.push(u); insta[u] = true;
    for(node *p=adj[u];p;p=p->next){
        int v = p->v;
        if(!dfn[v]){
            dfs(v);
            low[u]=  min(low[u], low[v]);
        }else if(insta[v])
            low[u] = min(low[u], dfn[v]);
    }
    if(dfn[u] == low[u]){
        int tmp; ++kcnt;
        do{
            tmp = sta.top();
            id[tmp] = kcnt;
            sta.pop();
            sz[kcnt]++;
            insta[u] = false;
        }while(tmp!=u);
    }
}
bool ans[MAXN+10];
void solve(){
    int n, m, u, v;
    scanf("%d%d", &n, &m);
    for(int i=1;i<=m;i++){
        scanf("%d%d", &u, &v);
        addedge(u, v);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs(i);
    //printf("%d\n", kcnt);
    for(int i=1;i<=n;i++)
        for(node *p=adj[i];p;p=p->next)
            if(id[p->v] != id[i])
                ans[id[i]] = true;
    int Print = 0;
    for(int i=1;i<=kcnt;i++)
        if(!ans[i]){
            if(Print){
                printf("0\n");
                return ;
            }
            Print = sz[i];
        }
    printf("%d\n", Print);
}
int main(){
    solve();

    return 0;
}

posted on 2015-07-24 10:20  JeremyGuo  阅读(184)  评论(0编辑  收藏  举报

导航