题目如下:
https://www.luogu.org/problemnew/show/P2341#sub
很明显,由于牛的爱慕会传递,a喜欢b,那么从a到b连一条有向边,跑一遍强连通分量,在一个强连通分量的人都互相爱慕,判断一个点能否被所有人喜爱故判断它是否能被所有强连通分量到达,也就是从该节点反向dfs若能到达所有强连通分量即可
代码如下,kosaraju缩点
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
struct Node{
int stime,etime,p;
}N[10010];
vector<int> E[10010],UE[10010],NE[10010],UNE[10010];
int n,m,vis[10010],step,vis2[10010],color[10010],count_color,sum,vis3[10010],colorsum[10010];
void dfs(int t){ //正图跑时间戳
if(!vis[t]){
N[t].stime=++step;
N[t].p=t;
vis[t]=1;
}
else return;
for(int i=0;i<E[t].size();i++) dfs(E[t][i]);
N[t].etime=++step;
}
void udfs(int t){//返图缩点
if(!vis2[t]){
vis2[t]=1;
color[t]=count_color;
colorsum[count_color]++;
}
else return;
for(int i=0;i<UE[t].size();i++){
udfs(UE[t][i]);
}
}
void change_map(){
for(int i=1;i<=n;i++) for(int j=0;j<E[i].size();j++) UE[E[i][j]].push_back(i);
}
void change_mapN(){
for(int i=1;i<=count_color;i++) for(int j=0;j<NE[i].size();j++) UNE[NE[i][j]].push_back(i);
}
void getmap(){
for(int i=1;i<=n;i++) for(int j=0;j<E[i].size();j++) if(color[i]!=color[E[i][j]]) NE[color[i]].push_back(color[E[i][j]]);
}
bool cmp(Node a,Node b){
return a.etime>b.etime;
}
void check(int t){
if(!vis3[t]){
vis3[t]=1;
sum++;
}
else return;
for(int i=0;i<UNE[t].size();i++) check(UNE[t][i]);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
E[u].push_back(v);
}
for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
change_map();
sort(N+1,N+n+1,cmp);
for(int i=1;i<=n;i++) if(!vis2[N[i].p]){count_color++;udfs(N[i].p);}
getmap();
change_mapN();
int ans=0;
for(int i=1;i<=count_color;i++){
if(!NE[i].size()&&!vis3[i]){
sum=0;
check(i);
if(sum==count_color) ans+=colorsum[i];
}
}
cout<<ans<<endl;
return 0;
}