Codeforces Round #467 (Div. 2) - D. Sleepy Game (找环)

版权声明:是自己手打的没错 https://blog.csdn.net/Mr_Treeeee/article/details/82913194

http://codeforces.com/contest/937/problem/D

题意:

给你一个有向图,A和B博弈,从一个S起点开始走,谁不能走了谁就输了。

B睡着了,A替B走。所以B可以很蠢。

如果A不能赢,那么看看A能不能使游戏永远进行下去。

否则只能输了。

POINT:

要赢肯定是有一条路径,走到尾的时候刚好是奇数步。

没有这种路径,就从S开始找能不能进入一个环。

还没有的话,就只能输了。

具体是,VIS[N][2],0代表走到这个点为偶数步,1为奇数步。

所以每个点最多只会被搜到2次。不会TLE。

如果不能赢,用SPFA从s开始搜,看看就没有环。(取所以点的入度最大的那个数,如果更新超过这个数,就有环。不能是n,会超时)。

也可以用dfs染色判环,这个更简单且优秀些。

#include <stdio.h>
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#define LL long long
const int N = 1e5+55;
vector<int>G[N];

int vis[N][2];
int flag=0;
int ans=0;
stack<int>q;
void dfs(int u,int k)
{
	if(vis[u][k]==1){
		return;
	}
	vis[u][k]=1;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		dfs(v,k^1);
		if(ans==1){
			q.push(u);
			return;
		}
	}
	if(G[u].size()==0&&k==1){
		q.push(u);
		ans=1;
	}
}
int n,m;
int col[N];
bool hasloop(int u)
{
	col[u]=1;
	for(int i=0;i<G[u].size();i++){
		int v=G[u][i];
		int f=0;
		if(col[v]==1) f=1;
		else if(col[v]==0) f=hasloop(v);
		if(f==1) return f;
	}
	col[u]=2;
	return 0;

}

int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		int k,x;scanf("%d",&k);
		while(k--){
			scanf("%d",&x);
			G[i].push_back(x);
		}
	}
	int s;scanf("%d",&s);
	dfs(s,0);
	if(ans==1){
		printf("Win\n");
		while(!q.empty()){
			printf("%d ",q.top());
			q.pop();
		}
	}else{
		if(hasloop(s)) printf("Draw\n");
		else printf("Lose\n");

	}
	

}

猜你喜欢

转载自blog.csdn.net/Mr_Treeeee/article/details/82913194