【好题】图论+思维——cf1344C/cf1345E
/* u<v,那么u->v连边,形成一个DAG 如果u选择的是全称量词,那么所有u出发可达的点v,显然有u<v,所以v必须是存在量词 所有可以到达u的点v,显然有u>v,所以v必须是存在量词 由于必须从左到右进行,所以如果a[i]是存在量词,那么a[i]可达的a[i+k],可达a[i]的a[i+k]都必须为存在量词 建立正反两张图 从1开始依次扫描下去,如果没确定是存在量词,那么就可以判定为全称量词 然后在两张图中把ai可达的点都访问一遍,标为存在量词 */ #include<bits/stdc++.h> using namespace std; #define N 300005 int n,m,in[N],ans[N],vis1[N],vis2[N]; vector<int>G1[N],G2[N]; void dfs1(int u){ vis1[u]=1; for(auto v:G1[u]) if(!vis1[v])dfs1(v); } void dfs2(int u){ vis2[u]=1; for(auto v:G2[u]) if(!vis2[v])dfs2(v); } int main(){ cin>>n>>m; for(int i=1;i<=m;i++){ int u,v; scanf("%d%d",&u,&v); in[v]++; G1[u].push_back(v); G2[v].push_back(u); } queue<int>q; int cnt=0; for(int i=1;i<=n;i++) if(in[i]==0)q.push(i); while(q.size()){ cnt++; int u=q.front();q.pop(); for(auto v:G1[u]){ in[v]--; if(in[v]==0) q.push(v); } } if(cnt!=n){puts("-1");return 0;} cnt=0; for(int i=1;i<=n;i++){ if(!vis1[i] && !vis2[i]){ cnt++;ans[i]=1; } if(!vis1[i])dfs1(i); if(!vis2[i])dfs2(i); } cout<<cnt<<'\n'; for(int i=1;i<=n;i++) if(ans[i])cout<<"A"; else cout<<"E"; }