【好题】图论+思维——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<<'
';
    for(int i=1;i<=n;i++)
        if(ans[i])cout<<"A";
        else cout<<"E";
}
原文地址:https://www.cnblogs.com/zsben991126/p/12849450.html