LOJ6033 "Yali training 2017 Day2" board game (game theory, a bipartite graph, Hungary algorithm)

What immortal ideas ah ......

The board would like to go see a bipartite graph.(Smg ah) (in fact, the school simulation game has essentially the same question, but directly gave a bipartite graph)

I want to go see a bipartite graph maximum matching.(How I think even the nature of the ring to go)

(The following is an excerpt here )

The maximum matching scheme some bipartite graph, the starting point from the non-match losing the upper hand: the upper hand only go match point (otherwise not the biggest match), just go straight match flip side to it is not possible when operating the upper hand went to non-matching points (otherwise there is augmenting path, and maximum matching contradiction), so losing the upper hand.

Easy to find, if and only if a certain starting point in the maximum matching, the upper hand will win.

(Note: I feel a little problem here, though I would be able to feel exactly why it is right, but I can not say, so the cushions)

Therefore, a starting point to win the upper hand if and only if it is certain maximum matching.

Judge, then, to find any one of the greatest matches. Then there is a match point, if there is a match point and he could find another match, then it does not actually legal, or legitimate.

Hungarian algorithm to do this with \ (O ((nm) ^ 2) \) . In fact constant is small, run dissatisfied, run fast.


Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=100010,mod=998244353,d[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline int read(){
    int x=0,f=0;char ch=getchar();
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,m,el,cnt,head[maxn],to[maxn],nxt[maxn],dis[maxn],with[maxn],x[maxn],y[maxn],id[111][111],tot;
char mp[111][111];
bool vis[maxn],ans[maxn];
inline void add(int u,int v){
    to[++el]=v;nxt[el]=head[u];head[u]=el;
}
void dfs(int u){
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(~dis[v]) continue;
        dis[v]=dis[u]^1;
        dfs(v);
    }
}
bool dfs2(int u){
    if(vis[u]) return false;
    vis[u]=true;
    for(int i=head[u];i;i=nxt[i]){
        int v=to[i];
        if(!with[v] || dfs2(with[v])){
            with[with[u]]=0;
            with[u]=v;with[v]=u;
            return true;
        }
    }
    return false;
}
int main(){
    n=read();m=read();
    FOR(i,1,n) scanf("%s",mp[i]+1);
    FOR(i,1,n) FOR(j,1,m) if(mp[i][j]=='.') id[i][j]=++cnt,x[cnt]=i,y[cnt]=j;
    FOR(i,1,n) FOR(j,1,m) if(mp[i][j]=='.'){
        FOR(k,0,3){
            int ti=i+d[k][0],tj=j+d[k][1];
            if(ti<1 || ti>n || tj<1 || tj>m || mp[ti][tj]=='#') continue;
            add(id[i][j],id[ti][tj]);
        }
    }
    MEM(dis,-1);
    FOR(i,1,cnt) if(dis[i]==-1) dis[i]=0,dfs(i);
    FOR(i,1,cnt) if(dis[i]){
        MEM(vis,0);
        dfs2(i);
    }
    FOR(i,1,cnt) if(with[i]){
        MEM(vis,0);
        ans[i]=!dfs2(with[i]);
    }
    FOR(i,1,cnt) if(!ans[i]) tot++;
    printf("%d\n",tot);
    FOR(i,1,cnt) if(!ans[i]) printf("%d %d\n",x[i],y[i]);
}

Guess you like

Origin www.cnblogs.com/1000Suns/p/11806024.html