POJ 2186 强联通分量

点击打开链接

题意:牛A喜欢牛B,若牛B喜欢牛C,则牛A喜欢牛C,问最后多少牛被其它全部牛喜欢

思路:用强联通分量进行缩点,最后形成的图是有向无环图DAG。而拓扑序的值为DAG的长度,则加一,可是最后我们要推断一下这些牛是不是被全部牛喜欢,由于等于DAG长度的全部点肯定是一个强联通分量,因此它们能够相互喜欢,我们用当中一仅仅牛推断即可了,推断时就用反向边推断这个牛能不能到达其它的牛即可了

#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=10010;
int V;
vector<int>G[maxn];
vector<int>rG[maxn];
vector<int>vs;
bool used[maxn];
int cmp[maxn];
void add_edge(int from,int to){
    G[from].push_back(to);
    rG[to].push_back(from);
}
void dfs(int v){
    used[v]=1;
    for(unsigned 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(unsigned 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));
    vs.clear();
    for(int v=0;v<V;v++){
        if(!used[v]) dfs(v);
    }
    memset(used,0,sizeof(used));
    int sum=0;
    for(int i=vs.size()-1;i>=0;i--){
        if(!used[vs[i]]) rdfs(vs[i],sum++);
    }
    return sum;
}
int main(){
    int m;
    while(scanf("%d%d",&V,&m)!=-1){
        for(int i=0;i<maxn;i++) G[i].clear();
        for(int j=0;j<maxn;j++) rG[j].clear();
        int a,b;
        for(int i=0;i<m;i++){
            scanf("%d%d",&a,&b);
            add_edge(a-1,b-1);
        }
        int t=scc(),ans=0,pos;
        for(int i=0;i<V;i++){
            if(cmp[i]==t-1){
                ans++;
                pos=i;
            }
        }
        memset(used,0,sizeof(used));
        rdfs(pos,0);
        for(int i=0;i<V;i++){
            if(used[i]==0){
                ans=0;break;
            }
        }
        printf("%d
",ans);
    }
    return 0;
}


原文地址:https://www.cnblogs.com/mthoutai/p/7363372.html