首先题目要求的牛要被所有的牛仰慕,那显然必须构成一个联通图
那么每一个点都要有入度或者出度,考虑这种情况:如果某只牛没有出度,那么就意味着他不仰慕别的牛只是被别人仰慕,由于又是 连通图,具题目要求仰慕又有传递性,那么必须这只牛被所有的牛仰慕,
现在假设这只牛变成了一个强连通分量,那么显然意味着这个分量里面的牛都被YM,所以解题的方法就应该是在缩点之后的图G中求出所有出度为零的点的个数,如果个数大于1,说明至少存在两个分量之间的牛不会相互YM,明显和题目要求不符合,输出0,如果等于1则说明只有一个强连通分量里面的牛被其他全部的牛YM,那么答案就是这个分量中点的个数
这题纠结了蛮久,之前对缩点后求度数不是很清楚,然后代码一直WA,在参阅了某MM的博客后做了多组数据,发现了不少bug,修改了好久才AC。。。唉。。。
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int size = 11000;
vector <int> mapp[size], remapp[size];
vector <int>comp[size];
vector <int>sccindex[size];
map <int, int> mak;
bool visited[size];
int num[size];
int belg[size];
int counter;
int n ;
int edge[5*size][2]; //0记录出点,1记录入点
void init()
{
for (int i = 0; i <= n; i ++){
mapp[i].clear(), remapp[i].clear(), comp[i].clear(), sccindex[i].clear();
}
mak.clear();
}
void dfs1(int v)
{
visited[v] = true;
for (int i = 0; i < mapp[v].size(); i ++){
int t = mapp[v][i];
if (!visited[t]){
dfs1(t);
}
}
num[++counter]= v;
}
int kk;
void dfs2(int v)
{
visited[v] = true;
sccindex[kk].push_back(v);//记录第kk个强连通分量中的点
mak[v] = kk;//记录第kk个点属于第几个强连通分量
for (int i = 0; i < remapp[v].size(); i ++){
int t = remapp[v][i];
if (!visited[t]){
belg[t] = kk;
dfs2(t);
}
}
}
void scc()
{
counter = 0;
memset(visited, false, sizeof(visited));
for (int i = 1; i <= n; i ++){
if (!visited[i]){
dfs1(i);
}
}
// cout<<"counter: "<<counter<<endl;
memset(visited, false ,sizeof(visited));
kk = 0;
for (int i = counter; i >= 1; i --){
int k = num[i];
if (!visited[k]){
visited[k] = true;
++ kk;
dfs2(k);
}
}
}
void compress()
{
for (int i = 1; i <= n; i ++){
for (int j = 0; j < mapp[i].size(); j ++){
if (belg[mapp[i][j]] != belg[i]){
comp[belg[i]].push_back(belg[mapp[i][j]]);
}
}
}
}
int main()
{
//freopen("IN.txt", "r", stdin);
//freopen("OUT.txt", "w", stdout);
int m;
while (scanf("%d%d", &n, &m) != EOF){
init();
int t;
int a, b;
for (int i = 0; i < m; i ++){
scanf("%d%d", &a, &b);
edge[i][0] = a;
edge[i][1] = b;
mapp[a].push_back(b);
remapp[b].push_back(a);
}
scc();
compress();
int OUT[size] = {0};
int maxx = -1;
for (int i = 0; i < m; i ++){
a = mak[edge[i][0]], b = mak[edge[i][1]];//a,b表示每个出点入点所在的强连通分量位置
if (a != b){
OUT[a] ++;
}
}
int ans = 0;
int id;
for (int i = 1; i <= kk; i ++){
if (!OUT[i]){ans ++;id = i;}
}
if (ans == 1){
printf("%d\n", sccindex[id].size()) ;
}
else
printf("0\n");
}
return 0;
}