题意:给你一张n个点的有向图,并给你B和A的初始坐标(点号)。B和A在图上轮流走,B先走。如果某个时刻A和B在同一点上了,B就输了,B的胜利的条件是B和A永远都不会重合,如果有一方不能走了,那么那一方就输了。
思路:f[i][j][0/1(0表示当前是A走,1表示当前是B走)]=0/1 (0表示B输,1表示B赢)
开始将f数组全初始化为1,将B必败初始化为0,并存入队列,然后BFS。
BFS时考虑两种情况。如果当前是动B,则上一步是动A,因为当前是B的必败态,上一个状态又是A,所以上一个状态也一定是B的必败态,然后将状态标记并且存入队列。
如果当前状态是动A,则上一个状态是动B,上一个状态一定是要是后继状态全是必败态才是必败态,所以用一个num数组来标记,每次找到B就将该状态加1,当这个值等于这个点的出度时,既所有后继状态都是必败态,所以此状态是必败态,标记并且存入队列。
最后访问一下就好了
#include<bits/stdc++.h>
using namespace std;
#define maxn 111
int imp[maxn][maxn];///正向图
int mp[maxn][maxn];///反向图
bool f[maxn][maxn][2];///ia的位置,jb的位置,0a先,1b先; 值0 b败 值1 b胜
bool vis[maxn][maxn][2];///上述状态有没有访问过
int num[maxn][maxn][2];///如果是b的必败态被访问的次数
int out[maxn]; ///每个点的出度
struct NODE {
int a,b,op;///a位置,b位置
NODE(int aa,int bb,int oop) {
a=aa;
b=bb;
op=oop;
}
};
int main()
{
int t,n,m;
int kase=0;
scanf("%d",&t);
while(t--) {
memset(imp,0,sizeof imp);
memset(mp,0,sizeof mp);
memset(vis,0,sizeof vis);
memset(out,0,sizeof out);
memset(num,0,sizeof num);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
f[i][j][0]=f[i][j][1]=1;
int x,y;
int ex,ey;
for(int i=1;i<=m;i++) {
scanf("%d%d",&x,&y);
imp[x][0]++;
imp[x][imp[x][0]]=y;
mp[y][0]++;
mp[y][mp[y][0]]=x;
out[x]++;
}
scanf("%d%d",&ex,&ey);
queue<NODE> gg;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
for(int k=0;k<=1;k++) {
if(i==j) {
f[i][j][k]=0;
NODE xx(i,j,k);
gg.push(xx);
vis[i][j][k]=1;
continue;
}
if(k==1) {
if(imp[j][0]==0) {
f[i][j][k]=0;
NODE xx(i,j,k);
gg.push(xx);
vis[i][j][k]=1;
}
continue;
}
}
/* cout << "*********************" << endl;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
cout << f[i][j][0] << " ";
cout << endl;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
cout << f[i][j][1] << " ";
cout << endl;
}
cout << "*********************" << endl;
cout << "????????????" <<gg.size() << endl;*/
while(!gg.empty()) {
NODE xx=gg.front();
gg.pop();
int xa=xx.a,xb=xx.b,xp=xx.op;
if(xp==0) ///当前动A,上一个动B
for(int i=1;i<=mp[xb][0];i++) {
int tt=mp[xb][i];
if(vis[xa][tt][1]==1) continue;
num[xa][tt][1]++;
if(num[xa][tt][1]==out[tt]) {
// cout << "当前状态:" <<xa <<" " << xb << " " << 0 << endl;
// cout << "上一个状态:" <<xa << " " << tt << " " << 1 << endl;
f[xa][tt][1]=0;
vis[xa][tt][1]=1;
NODE yy(xa,tt,1);
gg.push(yy);
}
}
if(xp==1) ///当前动B,上一个动A
for(int i=1;i<=mp[xa][0];i++) {
int tt=mp[xa][i];
if(vis[tt][xb][0]==1) continue;
// cout << "当前状态:" <<xa <<" " << xb << " " << 1 << endl;
// cout << "上一个状态:" <<tt << " " << xb << " " << 0 << endl;
f[tt][xb][0]=0;
vis[tt][xb][0]=1;
NODE yy(tt,xb,0);
gg.push(yy);
}
}
/* cout << "*********************" << endl;
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
cout << f[i][j][0] << " ";
cout << endl;
}
for(int i=1;i<=n;i++) {
for(int j=1;j<=n;j++)
cout << f[i][j][1] << " ";
cout << endl;
}
cout << "*********************" << endl;*/
if(f[ey][ex][1]==1) {
printf("Case #%d: Yes\n ",++kase);
}
else {
printf("Case #%d: No\n",++kase);
}
}
return 0;
}