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

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 InputSample 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] 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值