1. 程式人生 > >luogu4055 遊戲 (二分圖博弈)

luogu4055 遊戲 (二分圖博弈)

href target sin %s typedef 最大 fin style scanf

考慮對非障礙的點黑白染色然後做二分圖最大匹配,那麽有結論,先手必勝當且僅當不是完美匹配,而且可以放的點是那些可以不匹配的點

從非匹配點開始走,後手只能走到匹配點,於是先手就可以走匹配邊。由於不能走走過的點,所以現在又變成了一個非匹配點;這樣下去直到後手無路可走,所以先手必勝

反觀完美匹配的情況,先手放在任意一個匹配的位置,後手都可以走匹配邊從而變成了上面的情況,就是後手必勝

這類問題大概可以總結為:(一類可以用二分圖來描述的博弈問題)

1.博弈者人數為兩人,雙方輪流進行決策。
2.博弈狀態(對應點)可分為兩類(狀態空間可分為兩個集合),對應二分圖兩邊(X集和Y集)。任意合法的決策(對應邊)使狀態從一類跳轉到另一類。(正是由於這個性質使得問題可以用二分圖描述)

3.不可以轉移至已訪問的狀態。(不可重復訪問點)
4.無法轉移者判負。

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 #define MP make_pair
 5 #define fi first
 6 #define se second
 7 using namespace std;
 8 typedef long long ll;
 9 typedef unsigned long long ull;
10 typedef unsigned int ui; 11 typedef long double ld; 12 const int maxn=105,maxp=1e4+10; 13 14 inline char gc(){ 15 return getchar(); 16 static const int maxs=1<<16;static char buf[maxs],*p1=buf,*p2=buf; 17 return p1==p2&&(p2=(p1=buf)+fread(buf,1,maxs,stdin),p1==p2)?EOF:*p1++;
18 } 19 inline ll rd(){ 20 ll x=0;char c=gc();bool neg=0; 21 while(c<0||c>9){if(c==-) neg=1;c=gc();} 22 while(c>=0&&c<=9) x=(x<<1)+(x<<3)+c-0,c=gc(); 23 return neg?(~x+1):x; 24 } 25 26 int N,M,id[maxn][maxn],pct,cnt[2]; 27 char mp[maxn][maxn]; 28 bool col[maxp],flag[maxp],ans[maxp]; 29 int eg[maxp*4][2],egh[maxp],bel[maxp],ect; 30 31 inline void adeg(int a,int b){ 32 eg[++ect][0]=b,eg[ect][1]=egh[a],egh[a]=ect; 33 } 34 35 bool dfs(int x){ 36 for(int i=egh[x];i;i=eg[i][1]){ 37 int b=eg[i][0];if(flag[b]) continue; 38 flag[b]=1; 39 if(!bel[b]||dfs(bel[b])){ 40 bel[b]=x,bel[x]=b; 41 return 1; 42 } 43 }return 0; 44 } 45 46 int main(){ 47 //freopen("","r",stdin); 48 N=rd(),M=rd(); 49 for(int i=1;i<=N;i++) scanf("%s",mp[i]+1); 50 for(int i=1;i<=N;i++){ 51 for(int j=1;j<=M;j++){ 52 if(mp[i][j]==.){ 53 id[i][j]=++pct; 54 cnt[col[pct]=(i&1)^(j&1)]++; 55 if(i>1&&mp[i-1][j]==.) 56 adeg(id[i-1][j],id[i][j]),adeg(id[i][j],id[i-1][j]); 57 if(j>1&&mp[i][j-1]==.) 58 adeg(id[i][j-1],id[i][j]),adeg(id[i][j],id[i][j-1]); 59 } 60 } 61 } 62 int nn=0; 63 for(int i=1;i<=pct;i++){ 64 CLR(flag,0); 65 if(col[i]) nn+=dfs(i); 66 } 67 if(nn==cnt[0]&&nn==cnt[1]) puts("LOSE"); 68 else{ 69 puts("WIN"); 70 for(int i=1;i<=pct;i++){ 71 CLR(flag,0); 72 flag[i]=1; 73 if(!bel[i]||dfs(bel[i])) bel[i]=0,ans[i]=1; 74 } 75 for(int i=1;i<=N;i++){ 76 for(int j=1;j<=M;j++){ 77 if(ans[id[i][j]]) printf("%d %d\n",i,j); 78 } 79 } 80 } 81 return 0; 82 }

luogu4055 遊戲 (二分圖博弈)