题面
https://www.lydsy.com/JudgeOnline/problem.php?id=1443
题解
二分图博弈问题,找一定在匹配上的点,即求可能割边。
一定在最大流上的边竟然是可能割边,因为如果一条边一定在最大流上,把他删了最大流肯定会减少,也就是最小割会减少,所以是可能割边。
这是“最小”和“最大”性质的矛盾之处导致的。
#include<stack> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #define ri register int #define N 10500 #define S 0 #define T (wyr+1) using namespace std; const int dx[]={0,1,0,-1},dy[]={1,0,-1,0}; int n,m,bh[105][105],wyr; char g[105][105]; struct network_flow { vector<int> ed[N],to,w; int d[N],cur[N]; int bel[N],dfn[N],low[N],cc,cnt; bool ins[N]; stack<int> stk; void add_edge(int u,int v,int aw) { to.push_back(v); w.push_back(aw); ed[u].push_back(to.size()-1); to.push_back(u); w.push_back(0); ed[v].push_back(to.size()-1); } bool bfs() { queue<int> q; memset(d,0x3f,sizeof(d)); d[S]=0; q.push(S); while (!q.empty()) { int x=q.front(); q.pop(); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (w[e] && d[x]+1<d[to[e]]) { d[to[e]]=d[x]+1; q.push(to[e]); } } } return d[T]<1000000007; } int dfs(int x,int lim) { if (x==T || !lim) return lim; int sum=0; for (ri &i=cur[x];i<ed[x].size();i++) { int e=ed[x][i]; if (w[e] && d[x]+1==d[to[e]]) { int f=dfs(to[e],min(lim,w[e])); w[e]-=f; w[1^e]+=f; sum+=f; lim-=f; if (!lim) return sum; } } return sum; } int dinic() { int ret=0; while (bfs()) { memset(cur,0,sizeof(cur)); ret+=dfs(S,n*m+1); } return ret; } void tarjan(int x) { dfn[x]=low[x]=++cc; ins[x]=1; stk.push(x); for (ri i=0;i<ed[x].size();i++) { int e=ed[x][i]; if (!w[e]) continue; if (dfn[to[e]]) { if (ins[to[e]]) low[x]=min(low[x],dfn[to[e]]); } else { tarjan(to[e]); low[x]=min(low[x],low[to[e]]); } } if (dfn[x]==low[x]) { int t; ++cnt; do { t=stk.top(); stk.pop(); ins[t]=0; bel[t]=cnt; } while (t!=x); } } } G; bool check() { for (ri i=S;i<=T;i++) if (!G.dfn[i]) G.tarjan(i); for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) if (bh[i][j]) { if ((i+j)%2==1) { if (G.bel[bh[i][j]]!=G.bel[S] && !G.w[2*bh[i][j]-2]) ; else return 1; } else { if (G.bel[bh[i][j]]!=G.bel[T] && !G.w[2*bh[i][j]-2]) ; else return 1; } } return 0; } int main() { scanf("%d %d\n",&n,&m); memset(g,'#',sizeof(g)); for (ri i=1;i<=n;i++) scanf("%s",g[i]+1); wyr=0; for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) if (g[i][j]=='.') bh[i][j]=++wyr; for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) if (bh[i][j]) { if ((i+j)%2==1) G.add_edge(S,bh[i][j],1); else G.add_edge(bh[i][j],T,1); } for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) if (bh[i][j] && (i+j)%2==1) { for (ri k=0;k<4;k++) { int nx=i+dx[k],ny=j+dy[k]; if (bh[nx][ny]) G.add_edge(bh[i][j],bh[nx][ny],1); } } G.dinic(); puts(check()?"WIN":"LOST"); for (ri i=1;i<=n;i++) for (ri j=1;j<=m;j++) if (bh[i][j]) { if ((i+j)%2==1) { if (G.bel[bh[i][j]]!=G.bel[S] && !G.w[2*bh[i][j]-2]) ; else printf("%d %d\n",i,j); } else { if (G.bel[bh[i][j]]!=G.bel[T] && !G.w[2*bh[i][j]-2]) ; else printf("%d %d\n",i,j); } } return 0; }