2014西安赛区的H,是一道有向图上的博弈问题
首先我们要确定一下结束状态,一种是两点重合,还有一种是没法移动棋子
接下来我们把结束状态放在队列的队首,倒退之前的状态
我用1表示Alice必胜,2表示Bob必胜,3表示平局,分了4种情况
1、轮到Bob,状态为1,dp[x][y][1]=1,那么之前能到达y的点dp[x][v][0]=1
2、轮到Alice,状态为2,dp[x][y][0]=2,那么x的入度v,dp[v][y][1]=2
3、轮到Bob,状态为2,那么对于y的入度v,vis[x][v][y][0]=1,v不能移动到y
4、轮到Alice,状态为1,与3的情况类似
#include<bits/stdc++.h>
using namespace std;
const int maxn=100+10;
struct node
{
int x,y,st;
};
int dp[maxn][maxn][2],n,m,T,cnt[maxn][maxn][2];
bool vis[maxn][maxn][maxn][2];
queue<node> Q;
vector<int> g[maxn];
vector<int> h[maxn];
void work()
{
while(!Q.empty())
{
node x=Q.front();Q.pop();
if(x.st==1&&dp[x.x][x.y][x.st]==1)
{
for(int i=0;i<h[x.y].size();i++)
{
int v=h[x.y][i];
if(!dp[x.x][v][0])
{
dp[x.x][v][0]=1;
Q.push((node){x.x,v,0});
}
}
}
else if(x.st==0&&dp[x.x][x.y][x.st]==2)
{
for(int i=0;i<h[x.x].size();i++)
{
int v=h[x.x][i];
if(!dp[v][x.y][1])
{
dp[v][x.y][1]=2;
Q.push((node){v,x.y,1});
}
}
}
else if(x.st==0&&dp[x.x][x.y][x.st]==1)
{
for(int i=0;i<h[x.x].size();i++)
{
int v=h[x.x][i];
if(!vis[v][x.y][x.x][1])
{
vis[v][x.y][x.x][1]=1;cnt[v][x.y][1]++;
if(cnt[v][x.y][1]==g[v].size()&&!dp[v][x.y][1])
{
dp[v][x.y][1]=1;
Q.push((node){v,x.y,1});
}
}
}
}
else if(x.st==1&&dp[x.x][x.y][x.st]==2)
{
for(int i=0;i<h[x.y].size();i++)
{
int v=h[x.y][i];
if(!vis[x.x][v][x.y][0])
{
vis[x.x][v][x.y][0]=1;cnt[x.x][v][0]++;
if(cnt[x.x][v][0]==g[v].size()&&!dp[x.x][v][0])
{
dp[x.x][v][0]=2;
Q.push((node){x.x,v,0});
}
}
}
}
}
}
int main()
{
//freopen("test.in","r",stdin);
scanf("%d",&T);
for(int tt=1;tt<=T;tt++)
{
scanf("%d%d",&n,&m);
memset(dp,0,sizeof(dp));memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
for(int i=1;i<=n;i++)
{
h[i].clear();g[i].clear();
dp[i][i][0]=dp[i][i][1]=1;
Q.push((node){i,i,0});Q.push((node){i,i,1});
}
for(int i=1;i<=m;i++)
{
int u,v;scanf("%d%d",&u,&v);
h[v].push_back(u);
g[u].push_back(v);
}
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)
{
if(!g[i].size())
dp[i][j][1]=1;Q.push((node){i,j,1});
if(!g[j].size())
dp[i][j][0]=2;Q.push((node){i,j,0});
}
work();
int sx,sy;scanf("%d%d",&sx,&sy);
cout<<"Case #"<<tt<<": ";
if(dp[sx][sy][1]!=1) puts("Yes");
else puts("No");
}
return 0;
}