T122085 [SBCOI2020]时光的流逝

link

#include <bits/stdc++.h>
# define LL long long
using namespace std;

struct Edge{
    int to;
    int next;
}e1[500010], e2[500010];
int head1[100010];
int head2[100010];
int en1,en2;
int state[100010][2];
void add1(int from, int to){
    e1[en1].next=head1[from];
    e1[en1].to=to;
    head1[from]=en1;
    ++en1;
}
void add2(int from, int to){  //反向边
    e2[en2].next=head2[from];
    e2[en2].to=to;
    head2[from]=en2;
    ++en2;
}
int n,m,q;

struct Sta{
    int node;  //走到哪儿个点
    int ago;   //轮到谁走 0代表A,1代表B
    int res;   //结果是什么  0代表A赢,1代表B赢
};

int helper(int S, int T){
    memset(state,-1,sizeof(state));
    queue<Sta> q;
    for(int i=1;i<=n;i++){
        if(head1[i]==-1){      //对于没有出度的点,轮到谁走谁输,终点同理
            state[i][0]=1;     //轮到A走,则B赢
            state[i][1]=0;
            q.push({i,0,1});
            q.push({i,1,0});
        }
    }
    state[T][0]=1;
    state[T][1]=0;
    q.push({T,0,1});
    q.push({T,1,0});
    while(!q.empty()){
        auto cur=q.front();
        q.pop();
        int curnode=cur.node;
        int who=cur.ago;
        int curres=cur.res;
        if(curres==1-who){   //若轮到A走,但是B赢,则前一个点若轮到B走,则B赢; 若轮到B走,但是A赢,则前一个点若轮到A走,则A赢
            for(int i=head2[curnode];i!=-1;i=e2[i].next){
                if(state[e2[i].to][1-who]!=-1) continue;
                state[e2[i].to][1-who]=curres;
                q.push({e2[i].to,1-who,curres});
            }
            continue;
        }


        for(int i=head2[curnode];i!=-1;i=e2[i].next){  //对于每一个前面的点
            int nextnode=e2[i].to;
            if(state[nextnode][1-who]!=-1) continue;
            int nextwho=1-who;

            bool flag=false;
            for(int j=head1[nextnode];j!=-1;j=e1[j].next){  //向后的点若都是轮到A走A赢,或者轮到B走B赢,则该点必输
                if(state[e1[j].to][who]!=who){
                    flag=true;
                    break;
                }
            }
            if(!flag){
                state[nextnode][nextwho]=1-nextwho;
                q.push({nextnode,nextwho,1-nextwho});
            }
        }
    }
    return state[S][0];
}

int main(){
    memset(head1,-1,sizeof(head1));
    memset(head2,-1,sizeof(head2));
    scanf("%d %d %d", &n, &m, &q);
    for(int i=0;i<m;i++){
        int u,v;
        scanf("%d%d", &u, &v);
        add1(u,v);
        add2(v,u);
    }
    for(int i=0;i<q;i++){
        int S,T;
        scanf("%d%d", &S, &T);
        int res=helper(S,T);
        if(res==1) printf("-1
"); //在起点B赢
        else if(res==0) printf("1
"); //在起点A赢
        else {
            printf("0
");
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/FEIIEF/p/12909361.html