本弱一开始想就是所有点能到达一个点的点就符合条件,那么就反向建边,对于某个点能跑遍所有点就ans++.不过TLE了最后两个测试点(过了18个测试点hhhhh)。
正解:
既然喜欢可以传递,就是对一个强联通分量可以看作一个点,最后只能有一个强联通分量出度为0才有答案,如果有两个或以上,则图不联通,答案为0. 输出那个强联通分量的个数就行
#include <bits/stdc++.h>
using namespace std;
const int N = 20000;
const int M = 100000;
struct E{
int nxt,v;
};
E edge[M];
int a[M],b[M];
int head[M],cnt,num,n,m,out[N];
int low[N],dfn[N],book[N],belong[N],sum[N];
stack<int> s;
void tarjan(int u){
dfn[u] = low[u] = ++num;
s.push(u); book[u]=1;
for(int v,i=head[u];i;i=edge[i].nxt){
v = edge[i].v;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}else if(book[v])low[u] = min(low[u],dfn[v]);
}
if(dfn[u]==low[u]){
int v;
++cnt;
do{
v = s.top();
s.pop();
book[v] = 0;
belong[v] = cnt;
sum[cnt]++;
}while(u!=v);
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d %d",&a[i],&b[i]);
u = a[i]; v = b[i];
edge[i].v = v; edge[i].nxt = head[u]; head[u] = i;
}
for(int i=1;i<=n;i++)
if(!dfn[i]){
tarjan(i);
}
for(int i=1;i<=m;i++){
if(belong[a[i]]!=belong[b[i]]){
out[belong[a[i]]]++;
}
}
int flag=0,id;
for(int i=1;i<=cnt;i++){
if(!out[i]){
id = i;flag++;
if(flag>=2){
printf("0\n");return 0;
}
}
}
printf("%d\n",sum[id]);
return 0;
}