[bzoj1051]Popular Cows

刚刚被ysy在联考里虐了,差点爆tan(pi/4),只好来bzoj寻求安慰再被虐一次233

tarjan是什么智障东西不想打我好弱啊,tarjan都不会打)

Description

  每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。

Input

  第一行两个数N,M。 接下来M行,每行两个数A,B,意思是A认为B是受欢迎的(给出的信息有可能重复,即有可
能出现多个A,B)

Output

  一个数,即有多少头牛被所有的牛认为是受欢迎的。

Sample Input

3 3
1 2
2 1
2 3

Sample Output

1

HINT

 

100%的数据N<=10000,M<=50000
 
这道题很裸的SCC吧,鉴于网上tarjan的code太多了,我还是打一个丑丑的dfs凑个数吧(tarjan异端中的一股清流)
要注意图不联通的情况,这时候没有牛受欢迎。
 
代码:
#include<vector>
#include<cstdio>
#include<cstring>
using std::vector;
const int MAX_V=10000;
int V,M;
vector<int>G[MAX_V],rG[MAX_V];
vector<int>vs;
bool used[MAX_V];
int cmp[MAX_V];
void add_edge(int s,int t){G[s].push_back(t); rG[t].push_back(s);}
void dfs(int v){
    used[v]=1;
    for(int i=0;i<G[v].size();i++)if(!used[G[v][i]])dfs(G[v][i]);
    vs.push_back(v);
}
void rdfs(int v,int k){
    used[v]=1;
    cmp[v]=k;
    for(int i=0;i<rG[v].size();i++)if(!used[rG[v][i]])rdfs(rG[v][i],k); 
} 
int scc(){
    memset(used,0,sizeof(used));
    for(int v=0;v<V;v++)if(!used[v])dfs(v);
    memset(used,0,sizeof(used));
    int k=0;
    for(int i=vs.size()-1;i>=0;i--)if(!used[vs[i]])rdfs(vs[i],k++);
    return k;
}
int main(){
    scanf("%d%d",&V,&M);
    for(int i=0;i<M;i++){
        int a,b;scanf("%d%d",&a,&b);add_edge(a-1,b-1);
    }
    int n=scc(),u=0,num=0;
    for(int v=0;v<V;v++)if(cmp[v]==n-1)u=v,num++;
    memset(used,0,sizeof(used));
    rdfs(u,0);
    for(int i=0;i<V;i++)
        if(!used[i]){
            num=0;
            break;
        }
    printf("%d\n",num); 
    return 0;
}
View Code

 

posted @ 2017-08-14 12:15  AristocratMarser  阅读(172)  评论(0编辑  收藏  举报