當前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
P4055-[JSOI2009]游戏【网络流,博弈】
生活随笔
收集整理的這篇文章主要介紹了
P4055-[JSOI2009]游戏【网络流,博弈】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目鏈接:https://www.luogu.com.cn/problem/P4055
題目大意
n?mn*mn?m的網格有的不能走,走過的不能走。開始有一個棋子先手可以決定位置,然后后先手輪流走,不能走的就輸了,求先手的必勝開始位置。
解題思路
我們將圖二分圖染色,然后可以走的兩兩連邊。如果這張圖有完全匹配,那么可以發現無論先手走到哪個點,后手可以順著完全匹配的邊走,因為這個邊一定是先手沒有走過的。
如果圖沒有完全匹配,考慮勝負情況。此時對于一個匹配來說,圖上會有一些點刪除后不會影響最大匹配,如果先手選擇了這些不需要的點作為起點,那么后手無論走到哪先手就可以順著最大匹配的方法走了。
現在問題是考慮如何求出所有最大匹配的不需要點,我們可以先跑一遍網絡流。然后從源點出發走沒有流完的邊,這些邊可以作為當前匹配沒有匹配的邊或者增廣路,然后走到的所有左邊的點就是答案。而匯點同理,走流完的邊即可,走到的右邊的點就是答案。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define p(x,y) ((x)-1)*m+(y) using namespace std; const int N=110*110,inf=2147483647/3; const int dx[4]={1,-1,0,0},dy[4]={0,0,1,-1}; struct node{int to,next,w; }a[N<<3]; int n,m,s,t,tot=1,ls[N],dep[N],col[N]; bool v[110][110],flag,ans[N];char st[110]; queue<int> q; void addl(int x,int y,int w){a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;return; } bool bfs(){while(!q.empty())q.pop();q.push(s);memset(dep,0,sizeof(dep));dep[s]=1;while(!q.empty()){int x=q.front();q.pop();for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dep[y]||!a[i].w)continue;dep[y]=dep[x]+1;if(y==t)return 1;q.push(y);}}return 0; } int dinic(int x,int flow){int rest=0,k;if(x==t)return flow;for(int i=ls[x];i;i=a[i].next){int y=a[i].to;if(dep[x]+1!=dep[y]||!a[i].w)continue;rest+=(k=dinic(y,min(a[i].w,flow-rest)));a[i].w-=k;a[i^1].w+=k;if(rest==flow)return flow;}if(!rest)dep[x]=0;return rest; } void dfs(int x,int c){if(dep[x])return;dep[x]=1;if(col[x]==c)ans[x]=flag=1;for(int i=ls[x];i;i=a[i].next)if(a[i].w==c)dfs(a[i].to,c);return; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%s",st+1);for(int j=1;j<=m;j++)v[i][j]=(st[j]=='#');}s=0;t=p(n,m)+1;col[s]=col[t]=-1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){if(!v[i][j]){if((i+j)&1)addl(p(i,j),t,1),col[p(i,j)]=0;else{addl(s,p(i,j),1),col[p(i,j)]=1;for(int k=0;k<4;k++){int x=i+dx[k],y=j+dy[k];if(x<1||y<1||x>n||y>m||v[x][y])continue;addl(p(i,j),p(x,y),1);}}}}while(bfs())dinic(s,inf);memset(dep,0,sizeof(dep)); dfs(s,1);dfs(t,0);if(!flag)return printf("LOSE")&0;printf("WIN\n");for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(ans[p(i,j)])printf("%d %d\n",i,j);return 0; }總結
以上是生活随笔為你收集整理的P4055-[JSOI2009]游戏【网络流,博弈】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 蘑菇街网络抽检怎么处罚(蘑菇街被投诉后、
- 下一篇: P4254-[JSOI2008]Blue