Codeforces Gym 100548H - The Problem to Make You Happy 2014 ACM-ICPC 西安站

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35406909/article/details/83097621

Problem H. The Problem to Make You Happy

Input file: standard input Output file: standard output Time limit: 1 seconds Memory limit: 256 mebibytes

Problem Description

Alice and Bob are good friends, as in every other storyline. One day Alice and Bob are
playing an interesting game. The game is played on a directed graph with n vertices and m
edges, Alice and Bob have exactly one chess piece each. Initially, Bob’s chess piece is placed
on vertex x, while Alice’s chess piece is placed at vertex y. Bob plays first, then Alice, then
Bob, then Alice and so on.

During each move, the player must move his/her chess piece from the vertex his/her chess
piece currently at to an adjacent vertex, by traveling through exactly one directed edge.
(Remember that the game is played on a directed graph.) If someone can’t make such a
move, he/she will be considered to lose the game.

There’s one additional rule: at any time, if Bob and Alice’s chess pieces are at the same
vertex, then Alice is consider to be the winner and the game ends up immediately.
Now you are given the initial situation, could you determine who is the winner? Please
note that neither Bob nor Alice will make any mistakes during the game, i.e. they both play
optimally. In case that the game never ends up, Bob is considered to be the winner.

Input

The first line of the input gives the number of test cases, T. T test cases follow.
For each test case, the first line contains two integers n and m (2 ≤ n ≤ 100, 1 ≤
m ≤ n × (n − 1)). Next m lines, each line contains two integers b and e, indicating there
is one directed edge from vertex b to vertex e. Last line contains two integers x and y
(1 ≤ x, y ≤ n, x ̸= y), which are Bob and Alice’s initial position. The graph contains no
self-loops or duplicate edges.

Output

For each test case output one line “Case #x: y”, where x is the case number (starting from

  1. and y is “Yes” (without quotes) if Bob can win or the game never ends up, otherwise “No”
    (without quotes).
Sample Input Sample Output
3
5 3
1 2
3 4
4 5
3 1
4 3
1 2
2 3
3 4
1 2
3 3
1 2
2 3
3 1
2 1
Case #1: Yes
Case #2: No
Case #3: Yes


https://vjudge.net/contest/261254#overview

训练时,这题过了就出现了

首先,看到n很小,就知道可以暴力。


d p [ i ] [ j ] [ k ] dp[i][j][k] 表示Bob在 i 号点,Alice在 j 号点,当前为A/B走下一步。

由于游戏无限循环是Bob赢,所以先默认dp值为1,也就是先手赢。我们只要试图找到一种使得先手输的方法。

可以从题目所给两条输的规则出发,遍历所有状态,看能不能找到初始状态dp[x][y][0],找到则后手会赢,否则先手赢。



CSDN新编辑器太不友好了,准备跑路了。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <deque>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#include <iomanip>
#include <assert.h>
#define pb push_back
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
typedef double db;
typedef pair<int,int> pp;
const int maxn=105,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=acos(-1.0L);
bool dp[maxn][maxn][2],inque[maxn][maxn][2];
int cnt[maxn][maxn][2];
int head[maxn],out[maxn];
int num=0;

struct Edge {
	int from,to,pre;
};
Edge edge[maxn*2];

struct node {
	int x,y;
	bool z;
	node(int x,int y,bool z): x(x),y(y),z(z) {}
};

void addedge(int from,int to) {
	edge[num]=(Edge){from,to,head[from]};
	head[from]=num++;
}

int main() {
	int cas,t=0;
	scanf("%d",&cas);
	while (cas--) {
		int n,m;
		t++;
		scanf("%d%d",&n,&m);
		int x,y;
		num=0;
		mem0(out);
		memset(head,-1,sizeof(head));
		for (int i=1;i<=m;i++) {
			scanf("%d%d",&x,&y);
			addedge(y,x);
			out[x]++;
		}
		scanf("%d%d",&x,&y);
		memset(dp,-1,sizeof(dp));  //默认先手胜
		mem0(cnt);
		mem0(inque);
		queue<node> q;
		//0 Blose, 1 Bwin
		//0 bob, 1 alice
		for (int i=1;i<=n;i++) {
			dp[i][i][1]=0;
			dp[i][i][0]=0;
			inque[i][i][0]=inque[i][i][1]=1;
			q.push(node(i,i,0));
			q.push(node(i,i,1));
			if (out[i]==0) {
				for (int j=1;j<=n;j++) {
					if (i==j) continue;
					dp[i][j][0]=0;
					q.push(node(i,j,0));
					inque[i][j][0]=1;
				}
			}
		}
		while (!q.empty()) {
			node now=q.front();
			q.pop();
			if (now.z==1) {
				for (int i=head[now.x];i!=-1;i=edge[i].pre) {
					int to=edge[i].to;
					cnt[to][now.y][!now.z]++;
					if (cnt[to][now.y][!now.z]==out[to]) {  //先手所有转移都必败
						dp[to][now.y][!now.z]=0;
						if (!inque[to][now.y][!now.z]) {
							inque[to][now.y][!now.z]=1;q.push(node(to,now.y,!now.z));
						}
					}
				}
			} else {
				for (int i=head[now.y];i!=-1;i=edge[i].pre) {
					int to=edge[i].to;
					if (!dp[now.x][now.y][now.z]) {   //后手找到一种必败
						dp[now.x][to][!now.z]=0;
						if (!inque[now.x][to][!now.z]) {
							inque[now.x][to][!now.z]=1;q.push(node(now.x,to,!now.z));
						}
					}
				}
			}
		}
		printf("Case #%d: ",t);
		if (dp[x][y][0]==1) printf("Yes\n"); else printf("No\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_35406909/article/details/83097621