博弈论初探----DAG上的NIM
2016-07-17 23:37
323 查看
题目
给定一个DAG,起点1出有一个棋子,先手后手依次将他向出边移动,最先无法移动的人输,求先手是否必胜。 //因为只要能转移到任意的对手的必败态,便为必胜态,反之为必败态,故只会有必胜/必败态存在。
代码
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #define maxn 10010 #define maxm 10010 using namespace std; struct Edge{ int u; int v; Edge *next; } edge[maxm]; bool win[maxn]; int n, m; int out_edge[maxn]; int topo_queue[maxn], q_end = 0, q_begin = 0; Edge *V[maxn]; int main() { cin >> n >> m; memset(out_edge, 0, sizeof(out_edge)); for (int i = 1; i <= m ; i++) { cin >> edge[i].u >> edge[i].v; edge[i].next = V[edge[i].v]; V[edge[i].v] = &edge[i]; out_edge[edge[i].u]++; }//邻接表储存,同时记录出度。 for(int i = 1; i <= n; i++) if(!out_edge[i]) topo_queue[q_end++] = i;//将所有出度为0的点加入处理队列中 for(int i = 0; i < q_end; i++) win[i] = false; //所有点初始为先手无法必胜,因先手到达无法走的点即败 while(q_begin < q_end) { int i = topo_queue[q_begin++]; win[i] = !win[i]; //win[i]表示以i点位起点,先手是否必胜,这里将之前表示的能否到达先手必败态的节点 反转为先手是否必胜 for(Edge *e = V[i]; e; e = e->next) { if(--out_edge[e->u] == 0) { win[e->u] = win[i] || win[e->u];//只要以此节点为起点走能转移到任意一个先手必胜态的起点,此节点先手必败。 // 这里记录的是能否到达一个先手必胜态的起点。当此节点出队时再反转结果 topo_queue[q_end++] = e->u; } } //toposort删边过程 } //toposort过程 if(win[1]) cout << "win"; else cout << "lose"; return 0; }
ps:最近代码风格变化的略快略多啊。。。
相关文章推荐
- 博弈论
- IT审计【转载】
- TopCoder SRM 558 DIV2 Level 3:CatAndRabbit
- 博弈论——取石子问题
- 2014年7月23日比赛题目
- CodeForces 197A
- [BZOJ1022][SHOI2008][博弈论][Nim游戏]小约翰的游戏
- POJ 3480 John
- poj1704 Georgia and Bob
- 博弈论(n堆硬币)
- 基本假设
- 取石子问题
- 博弈论四种类型之完全信息静态博弈
- hdu 1846 Brave Games
- hdu 1847 Good Luck in CET-4 Everybody!
- hdu 2516 取石子游戏(FIB博弈)
- hdu 1907 && hdu 2509(Nim博弈)
- 尼姆博弈和巴什博弈
- 博弈论-囚徒困境与重复囚徒困境的启示
- 博弈论入门