题解 CF1344C 【Quantifier Question】

pzc2004

2020-05-10 18:37:16

Solution

# 题目分析 建图+拓扑排序+dfs 先考虑-1的情况,如果存在一个环,那么一定不可以,否则就一定可以,判环可以用拓扑排序。 可以发现,如果 $X_i>X_j$ 或 $X_i<X_j(i<j)$ 那么 $Q_j$ 一定是E。 所以我们建两个图,一个图存正边,一个图存反边。然后从1扫到 $n$,对于当前的点 $i$,我们在正反图上都进行一次dfs,把遍历到的点都标记掉。如果点 $i$ 没有被标记,那么 $Q_i$ 就可以是A。 最后输出即可,复杂度 $O(N)$。 ``` cpp #include<bits/stdc++.h> using namespace std; #define N 200005 int n,m,ans,head1[N],head2[N],cnt1,cnt2,rd1[N],q[N],l=1,r,s,mi[N],ma[N]; int c[N],vis1[N],vis2[N]; struct sb//链式前向星存图 { int a,b; }e1[N],e2[N]; inline void add1(int a,int b) { e1[++cnt1].a=head1[a],e1[cnt1].b=b,head1[a]=cnt1; } inline void add2(int a,int b) { e2[++cnt2].a=head2[a],e2[cnt2].b=b,head2[a]=cnt2; } inline void dfs1(int x)//正图上dfs { vis1[x]=1; for(int i=head1[x];i;i=e1[i].a) { if(vis1[e1[i].b])continue; dfs1(e1[i].b); } } inline void dfs2(int x)//反图上dfs { vis2[x]=1; for(int i=head2[x];i;i=e2[i].a) { if(vis2[e2[i].b])continue; dfs2(e2[i].b); } } signed main() { scanf("%d%d",&n,&m); for(int i=1,a,b;i<=m;i++)scanf("%d%d",&a,&b),add1(a,b),add2(b,a),++rd1[b];//建正反图 for(int i=1;i<=n;i++)//拓扑排序 { ma[i]=i; if(rd1[i])continue; q[++r]=i; } while(l<=r) { ++s; int x=q[l++]; for(int i=head1[x];i;i=e1[i].a) { ma[e1[i].b]=min(ma[e1[i].b],ma[x]); --rd1[e1[i].b]; if(rd1[e1[i].b]==0)q[++r]=e1[i].b; } } if(s!=n){printf("-1");return 0;}//-1的情况 for(int i=1;i<=n;i++)//从1扫到n { if(!vis1[i] && !vis2[i])++ans,c[i]=1;//统计答案 dfs1(i),dfs2(i);//遍历 } printf("%d\n",ans); for(int i=1;i<=n;i++)if(c[i])printf("A");else printf("E"); return 0; } ```