首页 > 代码库 > UVA - 12163 Addition-Subtraction Game (博弈)

UVA - 12163 Addition-Subtraction Game (博弈)

Description

Download as PDF

 

You and your friend are playing a 2 player game. The game is played in a graph ofV vertices. The vertices are numbered from0 toV-1. The graph has some directed edges. But the graph does not contain any cycles or loops. The rule of the game is as follows.

1.      Initially vertex i has a positive value valuei

2.      Both players make their moves by turns. In his turn the player chooses a vertex with the following properties.

·         The value of the vertex is strictly positive.

·         The vertex has one or more outgoing edges.

If there is no such vertex the player loses and the game terminates.

3.      If the player can select a vertex the player will decrease the value of the selected vertexi by1. Then from the set of vertices which have an incoming edge from vertexi, the player will selectKi (this value will be given as input) vertices and increase the value of those vertices by1.  Among these selectedKi vertices there can be duplicated vertices. And if a vertex is selectedn times its value will be increased by1 every time. Or in another word its value will be increased byn. For example if theKi=6 and the selected vertex set is{2,2,2,3,3,5} thenvalue2 will be increased by3,value3 will be increased by 2 and value5 will be increased by1.

Now consider the graph on the right.

 

Let the values of K be {2,1,3,2}.

 

Now the value set {0,0,0,5} is a losing terminating position because the player cannot select any vertex which have outgoing edges and positive values.

For the value set {3,4,5,6} the current player can go to the following value states by1 move.

·         {2,5,6,6} – select the vertex 0, decrease its value by1. And increase both of1 and2 by1. Here K0=2.

·         {2,6,5,6} – select the vertex 0, decrease its value by1 and increase its adjacent1 by2. HereK0=2.

·         {2,4,7,6} – select the vertex 0, decrease its value by1 and increase its adjacent 2 by2. HereK0=2.

·         {3,3,5,7} – select the vertex 1, decrease its value by1 and increase its adjacent3 by1. HereK1=1.

·         {3,7,4,6} – select the vertex 2, decrease its value by1 and increase its adjacent1 by3. HereK2=3.

·         {3,5,4,8} – select the vertex 2, decrease its value by1 and increase its adjacent1 by1 and3 by 2. HereK2=3.

·         {3,6,4,7} – select the vertex 2, decrease its value by1 and increase its adjacent1 by2 and3 by 1. HereK2=3.

·         {3,4,4,9} – select the vertex 2, decrease its value by 1 and increase its adjacent 3 by 3. HereK2=3.

Now given the graph and initial values of each of the vertices your task is to determine if the first player wins or loses given that both players play perfectly.

 

Input

Input contains multiple number of test cases. First line contains T(1 ≤ T ≤ 20) the number of test cases. Each test case starts with a lineV(2 ≤ V ≤ 100) andE(2 ≤ E ≤ 1500).V is the number of vertices andE is the number of edges. Each of the nextE lines contains2 integersFROM(0 ≤ FROM < V) andTO(0 ≤ TO < V) denoting that there is a directed edge fromFROM toTO.FROM and TO will not be equal. Also each vertex will have at most 15 outgoing edges.  Next line containsV integersK0, K1,…KV-1. Each of the value ofK is between1 and 100 inclusive. Next line containsR(1 ≤ R ≤ 100) the number of rounds. There will beR round of game with this graph. Each of the nextR lines contains the description of each round. Each round consists ofV integersValue0 Value1 …ValueV-1 denoting the initial value of each vertex. Each of theseValuei will be between1 and 100 inclusive.

 

Output

For each test case output consist of R+1lines. First line is “Game#i:” where iis the game number. Game number starts from1. Each of the nextR lines contains“Round#j: RESULT”  wherej is the number of round.RESULT is eitherWINNING when the initial values of this round is a winning position for the first player orLOSING when the initial values of this round is a losing position for the first player. We will assume that both players play perfectly. Print a blank line after the output of each test case. See the output for sample input for more clarification.

Sample Input                               Output for Sample Input

2

3 3

1 0

2 0

1 2

0 2 2

5

3 0 0

4 1 0

5 0 1

1 1 1

2 2 2

4 3

0 1

1 2

2 3

3 2 1 0

5

0 0 0 0

0 0 0 1

0 0 1 0

0 1 0 0

1 0 0 0

 

Game#1:

Round#1: LOSING

Round#2: WINNING

Round#3: WINNING

Round#4: WINNING

Round#5: LOSING

 

Game#2:

Round#1: LOSING

Round#2: LOSING

Round#3: WINNING

Round#4: WINNING

Round#5: LOSING

题意:给有向图,给你n个结点,每个结点有值,还有个k[i]值,每次选个结点,值-1,而且选k个它邻接的点值+1(可以重复选),每个结点的邻接结点不会超过15,不能操作的算输,计算先手的输赢

思路:有向图上的组合游戏,没有邻接结点的SG值为0,然后计算出每个结点的SG值,当前结点的后继状态应该是它的叶子结点的状态组合,这样的话我们试着去枚举改变的子结点,也就是我们要让子结点执行奇数次的点(偶数来说是没有影响的),所以对于最多15个邻接结点我们需要遍历的去选择要执行奇数个次的结点来组成当前结点的SG值,为了确保能够正确的执行,我们需要选出来点的个数和k值奇偶相同,这样我们就能不重复的遍历到所有的后继状态了,最后每轮计算的时候,对于偶数的我们可以忽略不计,因为这不影响结果,我们只计算奇数的,把它当1处理

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
#include <map>
using namespace std;
const int maxn = (1<<15);
const int N = 105;

int n, m, t, k[N], sg[N], cnt[maxn];
vector<int> g[N];

int bitcount(int x) {
	int ans = 0;
	while (x) {
		ans += (x & 1);
		x >>= 1;
	}
	return ans;
}

int dfs(int u) {
	if (sg[u] != -1)
		return sg[u];
	if (g[u].size() == 0)
		return sg[u] = 0;
	for (int i = 0; i < g[u].size(); i++)
		dfs(g[u][i]);
	int Max = (1<<g[u].size());
	map<int, int> vis;
	for (int i = 0; i < Max; i++) {
		if (cnt[i] > k[u])
			continue;
		if ((cnt[i]^k[u]) & 1)
			continue;
		int x = 0;
		for (int j = 0; j < g[u].size(); j++)
			if (i & (1<<j))
				x ^= sg[g[u][j]];
		vis[x] = 1;
	}
	for (int i = 0; ; i++)
		if (!vis.count(i))
			return sg[u] = i;
}

void SG() {
	memset(sg, -1, sizeof(sg));
	for (int i = 0; i < n; i++)
		dfs(i);
}

int main() {
	for (int i = 1; i < maxn; i++)		
		cnt[i] = bitcount(i);
	int t, u, v,cas = 1;
	scanf("%d", &t);
	while (t--) {
		scanf("%d%d", &n, &m);
		for (int i = 0; i < N; i++)
			g[i].clear();
		for (int i = 0; i < m; i++) {
			scanf("%d%d", &u, &v);
			g[u].push_back(v);
		}
		for (int i = 0; i < n; i++)
			scanf("%d", &k[i]);
		SG();
		scanf("%d", &u);
		printf("Game#%d:\n", cas++);
		int r = 1;
		while (u--) {
			int ans = 0;
			for (int i = 0; i < n; i++) {
				scanf("%d", &v);
				if (v & 1)
					ans ^= sg[i];
			}
			printf("Round#%d: %s\n", r++, ans ? "WINNING" : "LOSING");
		}
		printf("\n");
	}
	return 0;
}








UVA - 12163 Addition-Subtraction Game (博弈)