题意:牛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; }