P6970 [NEERC2016] Game on Graph
P6970 [NEERC2016] Game on Graph
[NEERC2016] Game on Graph
题面翻译
Gennady 和 Georgiy 在玩一个有向图上的游戏。这个图有 \(n\) 个点 \(m\) 条边,两人轮流操作,每次可以将棋子沿着其中一条边移动,不能移动者输。
你要对于每个点,分别求出以这个店为起点开始游戏,两人分别作为先手,最终会输,赢,还是平局(游戏无限循环)。
其中,Gennady 因为玩得很开心,所以他更期望将游戏变为平局;Georgiy 还有很多其他事,所以他更期望游戏不要平局。当然,在不平局的基础上,两人都更希望赢。
输入格式
第一行两个数 \(n\),\(m\) 表示有 \(n\) 个点 \(m\) 条边。
接下来 \(m\) 行每行两个数 \(a,b\) 表示一条由 \(a\) 至 \(b\) 的边。
输出格式
两行,第一行表示分别以每一个点为起点 Gennady 先手的胜负情况;第二行表示分别以每一个点为起点 Georgiy 先手的胜负情况。W 表示赢,L 表示输,D 表示平局。
by a___
(1≤n≤100000)
(1≤m≤200000)
Time limit: 2 s, Memory limit: 512 MB.
---------------------------------------------------------------------------------------
将每个点拆成A,B两类;
对于一个点u及其邻居v:
用opt=0代表A类节点,opt=1代表B类节点
对于A类点v.A:
如果它的所有u.A已经被遍历过了,那就搜索v.a这个节点。
(因为A希望平局,所以要先确定他邻居点的状态再确定他)
对于B类点v.B:
如果它没有被访问过,那就访问v.B这个节点
(因为B不希望平局,所以只要能访问就访问)
注意:在主程序中用for遍历启动搜索时,只有那些d==0的节点才能被搜
(即状态已经确定的节点)
然后,我们在第一次搜索完之后统计所有节点的胜负
而对于胜负的判定:(对于第一次搜素)
若对于 vis[0][opt]=1:
说明其被访问过即度数已经为0则A输了,反之,暂定A赢了
若对于 vis[1][opt]=1:
说明其被访问过即度数已经为0则B赢了,反之,暂定B输了
(因为B在第一次dfs中为后手,所以要反过来)
再进行第二次搜索,而在两次搜索中都未被确定的节点就是平局了
然后这题就做完了
Code:
#include<bits/stdc++.h>
const int N=1e5+5;
using namespace std;
vector<int> E[N];
int d[N][2],vis[N][2];
char ans[2][N];
int n,m;
void dfs(int u,int opt)
{
vis[u][opt]=1;
for(int v : E[u])
{
d[v][opt^1]--;
if(opt==0&&vis[v][1]==0)dfs(v,1);//对于B类点,只要先前没遍历过,就搜一下
if(opt==1&&d[v][0]==0)dfs(v,0);//对于A类点,要等到所有邻居被访问过之后才能搜
}
}
void work()
{
cin>>n>>m;
for(int i=1,x,y;i<=m;i++)
{
scanf("%d%d",&x,&y);
E[y].push_back(x);//建反图,由已知确定未知
d[x][1]++,d[x][0]++;//两类点的度数
}
for(int i=1;i<=n;i++)
{
if(d[i][0]==0&&vis[i][0]==0)
{
dfs(i,0);
}
}
for(int i=1;i<=n;i++)
{
if(vis[i][0])
{
ans[0][i]='L';
}
else
{
ans[0][i]='W';
}
if(vis[i][1])
{
ans[1][i]='W';
}
else
{
ans[1][i]='L';
}
}
for(int i=1;i<=n;i++)
{
if(!d[i][1]&&!vis[i][1])dfs(i,1);
}
for(int i=1;i<=n;i++)
{
if(!vis[i][1])ans[1][i]='D';
if(!vis[i][0])ans[0][i]='D';
}
for(int opt=0;opt<2;opt++)
{
for(int i=1;i<=n;i++)
{
putchar(ans[opt][i]);
}
cout<<"\n";
}
}
int main()
{
//freopen("P6970.in","r",stdin);//freopen("P6970.out","w",stdout);
work();
}

浙公网安备 33010602011771号