bzoj 1051

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1051相关的知识,希望对你有一定的参考价值。

如果A认为B是受欢迎的,B认为C是受欢迎的,C认为A是受欢迎的,这时形成了一个环。

这时如果A认为D是受欢迎的,那么B和C也认为D是受欢迎的。

于是要考虑缩点。为了好打邻接表用了vector代替。推荐用Tarjan或者Gabow算法。

缩点完最终只有可能有一个强连通分量的牛被全部牛认为是受欢迎的,或者直接没有。

如果有超过一个的强连通分量的出度为0那么没有牛被全部牛认为是受欢迎的。

否则就直接输出那个出度为0的强连通分量中牛的个数。

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=10001;
const int maxm=50001;
int read(){
    char c; while(!isdigit(c=getchar())); int x=c-0;
    while(isdigit(c=getchar())) x=x*10+c-0; return x;
}
vector<int> e[maxn];
int top,cnt,tme,vis[maxn],low[maxn],dfn[maxn],sta[maxn],num[maxn],dis[maxn],peo[maxn];
void tarjan(int o){
    low[o]=vis[sta[++top]=o]=++tme;
    for(int i=0;i<e[o].size();i+=1)
        if(!dfn[e[o][i]]){
            if(!vis[e[o][i]]) tarjan(e[o][i]);
            low[o]=min(low[e[o][i]],low[o]);
        }
    if(vis[o]==low[o]){
        ++cnt;
        while(dfn[sta[top]]=cnt,peo[cnt]+=1,sta[top--]!=o);
    }
}
int main(){
    int n=read(),m=read(),ans=0;
    while(m--){
        int a=read(),b=read();
        e[a].push_back(b);
    }
    for(int i=1;i<=n;i+=1) if(!dfn[i]) tarjan(i);
    int tot=0,pre=0;
    for(int i=1;i<=n;i+=1)
        for(int j=0;j<e[i].size();j+=1)
            if(dfn[i]!=dfn[e[i][j]]) dis[dfn[i]]=1;
    for(int i=1;i<=cnt;i+=1) if(!dis[i]) tot+=1,pre=i;
    if(tot==1) printf("%d",peo[pre]); else printf("0");
    return 0;
}

 

以上是关于bzoj 1051的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1051: [HAOI2006]受欢迎的牛 强连通缩点

bzoj1051: [HAOI2006]受欢迎的牛(强联通)

BZOJ 1051[HAOI2006]受欢迎的牛

BZOJ 1051 受欢迎的牛

bzoj1051

bzoj1051HAOI2006受欢迎的牛