ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

P4055 [JSOI2009] 游戏 / YbtOJ「图论」第1章 二分图匹配 F. 游戏 题解--zhengjun

2022-06-29 22:02:29  阅读:152  来源: 互联网

标签:head 匹配 游戏 -- 题解 int edge kk return


思路

考虑先对各点黑白染色,然后对于相邻的点连边建出二分图。

如果这个二分图有完全最大匹配(即每个点都匹配到了),那么先手必败,因为无论选那个点,后手只要向这个点匹配的另一个点走就行了。

如果是不完全最大匹配,那么先手必胜。

所以先手只要选到不一定在最大匹配中的点开始就一定赢,因为无论接下来后手走到哪里,先手只要跟着走到下一个匹配的点就行了。

所以只要先跑出一种最大匹配,然后从源点汇点分别 dfs 一遍就行了。

代码

#include<bits/stdc++.h>
#define edg(i,u) for(int i=head[u],v;v=edge[i].to,i;i=edge[i].nex)
using namespace std;typedef long long ll;const int N=5e2+10,M=N*N,K=M*5;char a[N][N];
int n,m,k,s,t,head[M],kk=1,d[M],cur[M],tag[M],ans[M],vis[M];struct edges{int to,c,nex;}edge[K];
void add(int u,int v,int c){edge[++kk]={v,c,head[u]};head[u]=kk;edge[++kk]={u,0,head[v]};head[v]=kk;}
int id(int x,int y){return (x-1)*m+y;}
bool chk(int x,int y){return x>0&&y>0&&x<=n&&y<=m&&a[x][y]=='.';}
bool bfs(){
	queue<int>q;q.push(s);memset(d,-1,sizeof d);d[s]=0;cur[s]=head[s];for(int u;!q.empty();q.pop()){
		u=q.front();edg(i,u)if(!~d[v]&&edge[i].c)q.push(v),d[v]=d[u]+1,cur[v]=head[v];
	}return ~d[t];
}
int dfs(int u,int lim=1e9){
	if(u==t)return lim;int flow=0;for(int i=cur[u],v;v=edge[i].to,i&&flow<lim;i=edge[i].nex){
		cur[u]=i;if(d[v]!=d[u]+1||!edge[i].c)continue;int f=dfs(v,min(lim-flow,edge[i].c));
		if(!f)d[v]=-1;edge[i].c-=f;edge[i^1].c+=f;flow+=f;
	}return flow;
}
int dinic(){int maxflow=0;for(;bfs();)maxflow+=dfs(s);return maxflow;}
void get(int u,int t){if(vis[u])return;vis[u]=1;if(tag[u]+t==2)ans[u]=1;edg(i,u)if(edge[i].c==t)get(v,t);}
int main(){
	cin>>n>>m;for(int i=1;i<=n;i++)cin>>a[i]+1;for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)k+=a[i][j]=='.'&&(tag[id(i,j)]=((i+j)&1)+1);
	for(int i=1;i<=n;i++)for(int j=1;j<m;j++)if(a[i][j]=='.'&&a[i][j+1]=='.')(i+j)&1?add(id(i,j+1),id(i,j),1):add(id(i,j),id(i,j+1),1);
	for(int i=1;i<n;i++)for(int j=1;j<=m;j++)if(a[i][j]=='.'&&a[i+1][j]=='.')(i+j)&1?add(id(i+1,j),id(i,j),1):add(id(i,j),id(i+1,j),1);
	s=0;t=n*m+1;for(int i=1;i<t;i++)if(tag[i]==1)add(s,i,1);else if(tag[i]==2)add(i,t,1);
	if(dinic()*2==k)return puts("LOSE"),0;puts("WIN");get(s,1);memset(vis,0,sizeof vis);
	get(t,0);for(int i=1;i<t;i++)if(tag[i]&&ans[i])printf("%d %d\n",(i-1)/m+1,(i-1)%m+1);return 0;
}

标签:head,匹配,游戏,--,题解,int,edge,kk,return
来源: https://www.cnblogs.com/A-zjzj/p/16425055.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有