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

来源:互联网 发布:三玻两腔中空玻璃数据 编辑:程序博客网 时间:2024/06/09 20:39

题目问的是有多少个牛收到所有的牛的喜欢,因为这道题目具有传递性,所以在有向图上找出强连通子图,可以发现每个子图中的奶牛一定是互相喜欢的,所以不用考虑这样的情况(把每一个强连通子图找出,缩点)然后整个图就变成了有向无环图,那么同一个点必须受到其他所有奶牛的喜欢,那么它不能喜欢任意的除了自己这个联通子图的牛的其他牛(会形成环)所以统计一下是否存在出度为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;}
0 0
原创粉丝点击