题意:
给你这么一个关系:
让你确定Q序列,每个是∀或者∃,使得
成立
问你最多的∀可以有多少并且将Q序列输出(不懂看样例3)
题解:
很明显,它题目里都说了
上面是合法的,下面是不合法的,然后根据逻辑推一推就可以知道,如果有这样一个关系a,b。
无论a,b谁在前在后,只有序号比较小的那个能够是∀,剩下一个一定是∃,比如
x1<x2
那么只能x1是∀
x2<x1
依然是x1为∀
推广到更多的情况:一条有向路径上,只有序列最小的那个数才有∀
那么我们dfs做一遍拓扑+DP即可
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int pmi[N],smi[N],ans[N],deg[N],f,sum;
vector<int>son[N];
void dfs(int num,vector<int>vec){
if(!num){
for(int i:vec){
if(pmi[i]>=i)sum++,ans[i]=1;
}
return ;
}
if(vec.empty()){
printf("-1\n");
exit(0);
}
vector<int>ne;
int del=0;
for(int u:vec){
for(int i:son[u]){
deg[i]--;
pmi[i]=min(pmi[i],pmi[u]);
if(!deg[i])
ne.push_back(i),del++;
}
}
dfs(num-del,ne);
for(int u:vec){
for(int i:son[u])
smi[u]=min(smi[u],smi[i]);
if(pmi[u]>=u&&smi[u]>=u)ans[u]=1,sum++;
}
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)pmi[i]=smi[i]=i;
for(int i=1;i<=m;i++)
scanf("%d%d",&x,&y),son[y].push_back(x),deg[x]++;
vector<int>vec;
for(int i=1;i<=n;i++)
if(!deg[i])
vec.push_back(i);
dfs(n-vec.size(),vec);
printf("%d\n",sum);
for(int i=1;i<=n;i++)
printf("%c","EA"[ans[i]==1]);
printf("\n");
return 0;
}