题解 P6560 [SBCOI2020] 时光的流逝

发布时间 2023-11-01 10:29:23作者: Tyrue

题解 P6560 [SBCOI2020] 时光的流逝

首先考虑图上的点为 \(y\) 终点时,或者这个点无法继续向下走,即 \(du_i = 0\) 时,从这个点为起点先手必败,而对于每一个有一条指向先手必败的点的边的点,显然从这个点出发都是先手必胜的,以此类推。

可以考虑建反图,进行拓扑排序,转移状态。

#include<queue>
#include<cstdio>
using namespace std;

int cnt;
int du[100010],head[100010],f[100010],d[100010];
queue<int> q;
struct Node{
	int to,nxt;
}edge[500010];

int read(){
	int res=0;char c=getchar();
	while(c>'9' || c<'0') c=getchar();
	while(c>='0' && c<='9') res=res*10+c-'0',c=getchar();
	return res;
}
int n=read(),m=read(),T=read();

int main(){
	for(int i=1;i<=m;i++){
		int x=read(),y;
		edge[++cnt]=((Node){x,head[y=read()]}),
		head[y]=cnt,du[x]++;
	}
	while(T--){
		int s=read(),t=read();
		for(int i=1;i<=n;i++){
			f[i]=0,d[i]=du[i];
			if(!d[i] || i==t) q.push(i),f[i]=-1;
		}
		while(q.size()){
			int p=q.front();q.pop();
			for(int i=head[p];i;i=edge[i].nxt)
				if(!f[edge[i].to]){
					if(f[p]==1){
						if(!(--d[edge[i].to])) q.push(edge[i].to),f[edge[i].to]=-1;
					}else q.push(edge[i].to),f[edge[i].to]=1;
				}
		}
		printf("%d\n",f[s]);
	}
	return 0;
}