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();
}