题意(跳过读题):给E,V~1e5的图,若无环,求有多少点,满足是其所在连通块上点值最小的点
写之前考虑的不是很充分,在图上的dfs要考虑到前后的点
正解为做正向和逆向的拓扑序来确定点是否满足条件
我可能是个傻子,这题还写一年。。
#include <bits/stdc++.h>
#define ll long long
#define mm(a,n) memset(a,n,sizeof(a))
#define tmp(x) std::cout<<"& "<<(x)<<" &\n"
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define per(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
const int maxn=2e5+100;
const int mo=998244353;
int ck[maxn],deg[maxn],vis[maxn],vs[maxn],vss[maxn],rdeg[maxn];
vector<int> g1[maxn],g2[maxn];
int n,m,u,v,pt;
inline int read(){
int x=0,f=1;
char c=getchar();
while(c>'9'||c<'0'){
if(c=='-')f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=x*10+c-'0';c=getchar();
}
return x*f;
}
queue<int> qq;
queue<int> q;
void topo(){
for(int i=1;i<=n;++i){
vs[i]=vss[i]=i;
if(!deg[i])vis[i]=1,q.push(i);
if(!rdeg[i])qq.push(i);
}
while(!q.empty()){
int x=q.front();q.pop();
for(int i=0;i<g1[x].size();++i){
vs[g1[x][i]]=min(vs[x],vs[g1[x][i]]);
if(--deg[g1[x][i]]==0)vis[g1[x][i]]=1,q.push(g1[x][i]);
}
}
while(!qq.empty()){
int x=qq.front();qq.pop();
for(int i=0;i<g2[x].size();++i){
vss[g2[x][i]]=min(vss[x],vss[g2[x][i]]);
if(--rdeg[g2[x][i]]==0)qq.push(g2[x][i]);
}
}
rep(i,1,n)if(!vis[i]){
printf("-1\n");return;
}
rep(i,1,n)if(vs[i]==i&&vss[i]==vs[i])++pt,ck[i]=1;
printf("%d\n",pt);
rep(i,1,n){
if(ck[i])printf("A");
else printf("E");
}
printf("\n");
}
int main() {
freopen("in.txt","r",stdin);
n=read(),m=read();
rep(i,1,m){
u=read(),v=read();
g1[u].push_back(v),g2[v].push_back(u);
++deg[v],++rdeg[u];
}
topo();
return 0;
}