Gym - 100548H The Problem to Make You Happy 2014-2015 ACM-ICPC, Asia Xian Regional Contest (BFS+博弈)

时间:2022-12-14 12:44:56

题意: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\n");
        else printf("No\n");
    }
    return 0;
}