「雅礼集训 2017 Day2」棋盘游戏

SOL:

   网络流神题,黑白染色比较显然吧。然后我们发现这是一个二分图匹配,大力胡一发,发现Alice走增广边,Bob走非增广边,那么当有完美匹配Alice就必胜了。

   但是我们发现对每一个点做一次最大流复杂度不科学,我们先随便找一个点,去找增广路就好了。

   

#include<bits/stdc++.h>
#define f(x) G.fall[G.head[x]]
#define exo(x) for(int i=head[x];i;i=net[i])
#define Exo(x) for(int& i=hea[x];i;i=net[i])
#define vv fall[i]
#define v G.fall[i]
#define eho(x) for(int i=G.head[x];i;i=G.net[i])
#define ha(x,y) ((x)*101+(y))
#define xh(x) x/101
#define yh(x) x%101
#define iha(i,j) (20000+ha(i,j))
#define N 120301
#define M 720301
#define inf (1<<29)
using namespace std;
int be,ed,in[N],n,m,p[2],S,T,x,que[N],idx;
int id[105][105],co[105*105],col[105][105],ok[105*105],vis[105*105];
int mx[]={1,-1,0,0},my[]={0,0,1,-1};
char mp[107][107];
struct Node{
    int tot,head[N],hea[N],net[M],fall[M],gap[N],SI,d[N],cost[M],que[N],s,t,x;
    Node() {tot=1;}
    inline void add(int x,int y,int co) {
        fall[++tot]=y; net[tot]=head[x]; head[x]=tot; cost[tot]=co;    
    }
    inline void adds(int x,int y,int co=1) {
        add(x,y,co),add(y,x,0);
    }
    void bfs() {
        memset(gap,0,sizeof gap); memset(d,0,sizeof d);
        memcpy(hea,head,sizeof head);
        que[be=0,ed=1]=t; gap[d[t]=1]=1;
        while (be<ed) {
            x=que[++be];
            exo(x) if (!d[vv])  que[++ed]=vv,gap[d[vv]=d[x]+1]++;
        }
    }
    int dfs(int x,int fl) {
        if (x==t) return fl;
        if (!fl) return 0;
        int tmp,flow=0;
        Exo(x) if (d[vv]+1==d[x]&& (tmp=dfs(vv,min(fl,cost[i])))) {
         fl-=tmp,flow+=tmp,cost[i]-=tmp,cost[i^1]+=tmp;
         if (!fl) return flow;
         }
        if (!(--gap[d[x]]))d[s]=SI;
        ++gap[++d[x]]; hea[x]=head[x]; return flow;
    }
    int isap(int S,int T,int SIZ){
        s=S; t=T; SI=SIZ+1; bfs(); 
        int flow=dfs(s,inf);
        while (d[s]<SI) 
         flow+=dfs(s,inf);
        return flow;
    }
}G;
#define sight(x) ('0'<=x&&x<='9')
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
inline void dfs0(int x){
    vis[x]=1;
    if(co[x]==1) ok[x]=1;
    eho(x) if(!vis[v]&&G.cost[i]==1) dfs0(v); 
}
inline void dfs1(int x){
    vis[x]=1;
    if(co[x]==0) ok[x]=1;
    eho(x) if(!vis[v]&&G.cost[i^1]==1) dfs1(v); 
}
signed main(){
//    freopen("a.in","r",stdin);
    read(n); read(m);
    for(int i=1;i<=n;++i) scanf("%s",mp[i]+1);
    S=++idx,T=++idx;
    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) {
        col[i][j]=(i+j)&1;
        if(mp[i][j]=='.') id[i][j]=++idx,co[idx]=col[i][j];
    }
    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(mp[i][j]!='#') {
        if(col[i][j]) G.adds(S,id[i][j]);
        else G.adds(id[i][j],T);
        if(col[i][j]) for(int k=0;k<4;++k) G.adds(id[i][j],id[i+mx[k]][j+my[k]]); 
    }
    cerr<<G.isap(S,T,n*m+2)<<endl;
    dfs0(S);
    memset(vis,0,sizeof(vis));
    dfs1(T);
    int ans=0;
    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) if(id[i][j]) ans+=ok[id[i][j]];
    writeln(ans);
    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) 
     if(ok[id[i][j]]) writel(i),writeln(j);
}

 

posted @ 2018-04-15 20:31  泪寒之雪  阅读(512)  评论(0编辑  收藏  举报