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 and 2 by1. Here K0=2.

·         {2,6,5,6} – select the vertex 0, decrease its value by1 and increase its adjacent1 by 2. 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 by 1. HereK1=1.

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

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

·         {3,6,4,7} – select the vertex 2, decrease its value by1 and increase its adjacent1 by 2 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 integers FROM(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;
}








Stkcd [股票代码] ShortName [股票简称] Accper [统计截止日期] Typrep [报表类型编码] Indcd [行业代码] Indnme [行业名称] Source [公告来源] F060101B [净利润现金净含量] F060101C [净利润现金净含量TTM] F060201B [营业收入现金含量] F060201C [营业收入现金含量TTM] F060301B [营业收入现金净含量] F060301C [营业收入现金净含量TTM] F060401B [营业利润现金净含量] F060401C [营业利润现金净含量TTM] F060901B [筹资活动债权人现金净流量] F060901C [筹资活动债权人现金净流量TTM] F061001B [筹资活动股东现金净流量] F061001C [筹资活动股东现金净流量TTM] F061201B [折旧摊销] F061201C [折旧摊销TTM] F061301B [公司现金流1] F061302B [公司现金流2] F061301C [公司现金流TTM1] F061302C [公司现金流TTM2] F061401B [股权现金流1] F061402B [股权现金流2] F061401C [股权现金流TTM1] F061402C [股权现金流TTM2] F061501B [公司自由现金流(原有)] F061601B [股权自由现金流(原有)] F061701B [全部现金回收率] F061801B [营运指数] F061901B [资本支出与折旧摊销比] F062001B [现金适合比率] F062101B [现金再投资比率] F062201B [现金满足投资比率] F062301B [股权自由现金流] F062401B [企业自由现金流] Indcd1 [行业代码1] Indnme1 [行业名称1] 季度数据,所有沪深北上市公司的 分别包含excel、dta数据文件格式及其说明,便于不同软件工具对数据的分析应用 数据来源:基于上市公司年报及公告数据整理,或相关证券交易所、各部委、省、市数据 数据范围:基于沪深北证上市公司 A股(主板、中小企业板、创业板、科创板等)数据整理计算
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值