bzoj 1443: [JSOI2009] Game Bipartite Graph Game

Keywords: network

meaning of the title

Give a map of n*m, some of the lattices can't walk. First hand can choose a grid to start, then go to the back hand, then go to the first hand. Each lattice can only walk once, and the one who can't walk is the loser. Ask which lattices you want to win first.
n,m<=100

Analysis

Consider black and white coloring first, then it becomes a bipartite graph, and then find out the maximum matching of the bipartite graph.
Suppose that the first hand chooses a non-matching point, then the second hand can only go along the matching point, and then the first hand goes along the matching point. If one time the latter reaches a mismatch point, there will be an augmented path, which contradicts the maximum match, so the first hand will win.
But what if all points match best? Whichever point you choose first, the latter can go along its matching. Then if you go first, it is a new maximum matching midpoint. Then the latter goes on its matching, and the latter wins.
Then we have to consider how to find each mismatch point.
Run a wave of network flow, we dfs once, see from the source point to which dyeing points return to S set;
Once again, dfs, see from which dyeing points returned to T set can reach the confluence point.
These are the answers! (Pay attention to the directed edge when building the edge! The initial flow of reverse arc is 0!)
Why?
First of all, mismatches are bound to be swept.
Then is the feasible point in the matching point:
How will we sweep to these feasible points?
Take S-set as an example, we will sweep to a feasible point, then to a T-set, and then return to a matching point through the reverse arc of the flow, so that the matching point is feasible!

Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#define N 105
#define inf 0x3f3f3f3f
using namespace std;

int n,m,cnt,s,t,dis[N*N],cur[N*N],last[N*N],map[N][N],ans,dx[4]={1,0,-1,0},dy[4]={0,1,0,-1},cho[N*N],flag,vis[N*N],bel[N*N];
char ch[N];
struct edge{int to,next,c;}e[N*N*10];
queue <int> q;

int point(int x,int y)
{
    return (x-1)*m+y;
}

void addedge(int u,int v,int c)
{
    e[++cnt].to=v;e[cnt].c=c;e[cnt].next=last[u];last[u]=cnt;
    e[++cnt].to=u;e[cnt].c=0;e[cnt].next=last[v];last[v]=cnt;
}

bool bfs()
{
    for (int i=s;i<=t;i++)
        dis[i]=0;
    dis[s]=1;
    while (!q.empty()) q.pop();
    q.push(s);
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        for (int i=last[u];i;i=e[i].next)
            if (e[i].c&&!dis[e[i].to])
            {
                dis[e[i].to]=dis[u]+1;
                if (e[i].to==t) return 1;
                q.push(e[i].to);
            }
    }
    return 0;
}

int dfs(int x,int maxf)
{
    if (x==t||!maxf) return maxf;
    int ret=0;
    for (int &i=cur[x];i;i=e[i].next)
        if (e[i].c&&dis[e[i].to]==dis[x]+1)
        {
            int f=dfs(e[i].to,min(e[i].c,maxf-ret));
            ret+=f;
            e[i].c-=f;
            e[i^1].c+=f;
            if (ret==maxf) break;
        }
    return ret;
}

void dinic()
{
    while (bfs())
    {
        for (int i=s;i<=t;i++)
            cur[i]=last[i];
        ans+=dfs(s,inf);
    }
}

void Dfs(int x,int d)
{
    vis[x]=1;
    if (bel[x]==d)
    {
        cho[x]=1;
        flag=1;
    }
    for (int i=last[x];i;i=e[i].next)
        if (!vis[e[i].to]&&e[i].c==d) Dfs(e[i].to,d);
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%s",ch+1);
        for (int j=1;j<=m;j++)
            if (ch[j]=='#') map[i][j]=1;
    }
    cnt=1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (i%2==j%2&&!map[i][j])
                for (int k=0;k<4;k++)
                {
                    int p=i+dx[k],q=j+dy[k];
                    if (p<1||p>n||q<1||q>m||map[p][q]) continue;
                    addedge(point(i,j),point(p,q),1);
                }
    s=0;t=n*m+1;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (!map[i][j])
            {
                if (i%2==j%2) 
                {
                    addedge(s,point(i,j),1);
                    bel[point(i,j)]=1;
                }
                else addedge(point(i,j),t,1);
            }
    dinic();
    Dfs(s,1);
    memset(vis,0,sizeof(vis));
    Dfs(t,0);
    if (flag) printf("WIN\n");
    else printf("LOSE\n");
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (cho[point(i,j)]) printf("%d %d\n",i,j);
    return 0;
}

Posted by nomis on Tue, 02 Apr 2019 19:57:29 -0700