题目链接:
http://acm.bnu.edu.cn/v3/problem_show.php?pid=5722
题目分析:
单向无环图。
所有叶子节点的sg值为0,然后用sg函数的性质去求其他节点的sg值即可。
我先用拓扑排序,然后从出度为0 的节点开始计算sg值,但是WA了。思考了好久也没有想通问题出在哪里。然后在网上抄了一个求sg值的函数,结果AC了。错误原因有待进一步探究。
代码:
#include <cstdio>
#include <cstring>
#define N 1010
using namespace std;
int edge[N][N];
int sg[N];
void Init(int n);
int dfs(int n,int tol);
int main()
{
int n,m,x,y,pos;
while(scanf("%d",&n)+1&&n)
{
Init(n);
for(int i=0;i<n;++i)
{
scanf("%d",&x);
if(!x)
sg[i]=0;
for(int j=0;j<x;++j)
{
scanf("%d",&y);
edge[i][y]=1;
}
}
while(scanf("%d",&m)&&m)
{
int sum=0;
for(int i=0;i<m;++i)
{
scanf("%d",&pos);
sum^=dfs(pos,n);
}
if(sum)
puts("WIN");
else
puts("LOSE");
}
}
return 0;
}
void Init(int n)
{
for(int i=0;i<n;++i)
for(int j=0;j<n;++j)
edge[i][j]=-1;
for(int i=0;i<n;++i)
{
sg[i]=-1;
}
}
int dfs(int n,int tol) /* 典型求 SG 函数的办法,n表示要求的节点下标,tol是所有节点数目,下标从0开始 */
{
int i;
if(sg[n]!=-1) return sg[n];
bool vis[1010];
memset(vis,0,sizeof(vis));
for(i=0;i<tol;i++)
{
if(edge[n][i] != -1)
vis[dfs(i,tol)]=true;
}
i=0;
while(vis[i]) i++;
return sg[n]=i;
}
用vector优化了空间占用后的代码:
#include <cstdio>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#define LL long long
#define db double
#define pi acos(-1.0)
#define pr printf
#define mod
#define N 1010
using namespace std;
vector<int > c[N];
int sg[N];
void Init(int n)
{
for(int i=0;i<n;++i)
{
c[i].clear();
sg[i]=-1;
}
}
int dfs(int now,int n)
{
int i;
if(sg[now]!=-1)
return sg[now];
int vis[n];
for(i=0;i<n;++i)
vis[i]=0;
for( i=0;i<c[now].size();++i)
{
vis[dfs(c[now][i],n)]=1;
}
i=0;
while(vis[i])
i++;
sg[now] = i;
return sg[now];
}
int main()
{
int n,m,i,j,u,v,xi;
while(scanf("%d",&n)+1&&n)
{
Init(n);
for(i=0;i<n;++i)
{
scanf("%d",&xi);
if(!xi)
sg[i]=0;
while(xi--)
{
scanf("%d",&v);
c[i].push_back(v);
}
}
while(scanf("%d",&m)&&m)
{
int sum=0;
for(i=0;i<m;++i)
{
scanf("%d",&u);
sum^=dfs(u,n);
}
if(sum)
puts("WIN");
else
puts("LOSE");
}
}
return 0;
}