Gym - 100548H The Problem to Make You Happy2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)
【Gym - 100548H The Problem to Make You Happy2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)】天下之事常成于困约,而败于奢靡。这篇文章主要讲述Gym - 100548H The Problem to Make You Happy2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)相关的知识,希望能为你提供帮助。
题意:Bob和Alice在一张有向无环图上移动,给定二者的起点,Bob先手.Bob的失败条件是不能移动或者与Alice相遇.两个人都采取最优策略,求Bob是否会赢
分析:银牌题.先确定所有的失败状态,然后根据这些反向状态BFS.
用(dp[i][j][0or1])表示bob在i点,Alice在j点,当前移动的人是bob还是Alice的情况, bob是否必败.
首先能确定的是 (dp[i][j][0] = dp[i][j][1] = 0), 对于出度为0的点(i),(dp[i][j][0]= 0).
搜索时有两种状态:
一是当前手是Bob,上一次是Alice,因为两者都选择最优策略,所以Alice肯定会选择让Bob的必败的状态,所以能达到该状态的其余状态都是必败态,将其入队列.
二是当前为Alice,上一次是Bob.Bob肯定不会选择让自己必败的状态,除非它的每一个选择都会走到必败态.统计这个前驱状态会走到的必败态的个数,若此个数等于这个前驱点的出度,表示状态出发的所有状态,Bob都是必败,则这个状态也是必败,将其入队列.
#include <
bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = 1e2+5;
int x,y;
int dp[MAXN][MAXN][2];
int deg[MAXN];
//出度
int num[MAXN][MAXN];
//失败的标记
struct Edge{
int v,next;
}E[MAXN*MAXN] ,rE[MAXN*MAXN];
int rhead[MAXN],rtot,N, M;
void init()
{
memset(num,0,sizeof(num));
memset(deg,0,sizeof(deg));
memset(rhead,-1,sizeof(rhead));
rtot = 0;
}void rAddEdge(int u,int v)
{
rE[rtot] = (Edge){v,rhead[u]};
rhead[u] = rtot++;
}struct Node{
int a, b, cur;
};
bool BFS()
{
memset(dp, -1,sizeof(dp));
queue<
Node>
Q;
//从所有的必败态开始反着搜
for(int i=1;
i<
=N;
++i){
Q.push((Node){i,i,0});
//都是必败态
Q.push((Node){i,i,1});
dp[i][i][0] = dp[i][i][1] = 0;
if(!deg[i]){
for(int j=1;
j<
=N;
++j){
if(j==i) continue;
Q.push((Node){i,j,0});
dp[i][j][0] = 0;
}
}
}while(!Q.empty()){
Node x = Q.front();
Q.pop();
int a = x.a , b = x.b, cur = x.cur;
int nxt = cur^1;
if(!cur){//Bob
int u = b;
for(int i = rhead[u];
~i ;
i = rE[i].next){
int v = rE[i].v;
if(dp[a][v][1] ==-1){
dp[a][v][1] = 0;
Q.push((Node){a,v,1});
}
}
}else{//Alice
int u = a;
for(int i = rhead[u];
~i ;
i = rE[i].next){
int v = rE[i].v;
num[v][b]++;
if(num[v][b]>
= deg[v] &
&
dp[v][b][0]==-1){
dp[v][b][0] = 0;
Q.push((Node){v,b,0});
}
}
}
}
if(dp[x][y][0]==0) return false;
return true;
}int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T,cas=1;
scanf("%d",&
T);
while(T--){
init();
scanf("%d %d ",&
N, &
M);
int u, v;
while(M--){
scanf("%d %d",&
u, &
v);
rAddEdge(v,u);
//反向建图
deg[u]++;
}
scanf("%d %d", &
x , &
y);
printf("Case #%d: ",cas++);
if(BFS()) printf("Yes
");
else printf("No
");
}
return 0;
}
推荐阅读
- SpringMVC-HandlerMapping
- Android MVVM小结
- 安卓preview不显示的问题
- 当安卓手机的数据线接口损坏时,如何刷机RECOVERY
- 如何修复Windows 10屏幕变暗的问题(解决办法指南)
- 如何修复Windows 10 FFXIV错误90002(解决办法教程)
- 如何修复Microsoft Store错误0x80073D12(解决办法教程)
- 如何修复Windows 10游戏中没有声音的问题(解决办法介绍)
- 如何修复Windows 10音频错误0xc00d4e86(解决办法教程)