Test room 11 && 12: Matrix chess game && (bipartite graph matching)

topic:

 

 

 

analysis:

Like this, two colors, or square, so small range of data, the preferred bipartite graph matching.

By analyzing the problem, we can know that no matter how the exchange, the number of row or column 1 will not change.

The last requirement is that at least each row and each column to share a 1 ,.

One can imagine:

   Row position row

 

 

 Row by row to the position 1 connected edge, so as to match a row.

Removing the intermediate point is a bipartite graph matching, if and only if the number of matches == n legitimate.

 

 

#include<bits/stdc++.h>
using namespace std;
#define N 405
#define M 50005
#define ri register int
int read()
{
    int x=0,fl=1; char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') fl=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*fl;
}
int a[N][N],n,ans=0,head[M],nex[M],to[M],tot=0,match[M],vis[M],Ti=0;
void add(int a,int b) { to[++tot]=b; nex[tot]=head[a]; head[a]=tot; }
bool dfs(int u)
{
    if(vis[u]==Ti) return false;
    vis[u]=Ti; 
    for(ri i=head[u];i;i=nex[i]){
        int v=to[i];
        if(!match[v] || dfs(match[v])){
            match[v]=u; match[u]=v;
            return true;
        }
    }
    return false;
}
void init()
{
    for(ri i=0;i<=max(tot,2*n);++i) head[i]=to[i]=nex[i]=match[i]=vis[i]=0;
    tot=0; Ti=0; ans=0;
}
int main()
{
    freopen("f.in","r",stdin);
    freopen("f.out","w",stdout);
    int T=read();
    while(T--){
        init();
        n=read();
        for(ri i=1;i<=n;++i){
            for(ri j=1;j<=n;++j){
                a[i][j]=read();
                if(a[i][j]) add(i,j+n),add(j+n,i);//
            }
        }
        for(ri i=1;i<=n;++i){
            Ti++; ans+=dfs(i);
        }
        if(ans==n) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
/*
6
2
0 0
0 1
3
0 0 1
0 1 0
1 0 0

4
0 0 0 1
0 0 1 0
1 0 0 0
0 1 1 0
*/
View Code

 

topic:

 

 

 

 analysis:

 Without limiting barriers, directly on a question along the lines of, even rows to columns side (only put a line, one can only put a), running side bipartite graph matching.

More obstacles for the line, the equivalent of a line divided into many parts, each part can put a column also empathy.

After each section of the line will be split renumbered, you can connect with the column side.

The last answer is the maximum number of matches.

( I use the network stream )

#include<bits/stdc++.h>
using namespace std;
#define N 205
#define M 1000005
#define ri register int
int n,m,a[N][N],h[N][N],l[N][N],id[N][N],s,t;
char ss[N];
int cost[M],lev[M],head[M],nex[M<<1],to[M<<1],tot=1,hang,lie;
queue<int> q;
void add(int a,int b,int ww)
{
    //printf("%d %d %d\n",a,b,ww);
    to[++tot]=b; nex[tot]=head[a]; head[a]=tot; cost[tot]=ww;
    to[++tot]=a; nex[tot]=head[b]; head[b]=tot; cost[tot]=0;
}
bool bfs()
{
    memset(lev,-1,sizeof(lev));
    lev[s]=0; q.push(s);
    while(!q.empty())
    {
        int u=q.front(); q.pop();
        for(int i=head[u];i!=-1;i=nex[i])
        {
            int v=to[i];
            if(cost[i]!=0&&lev[v]==-1)
            lev[v]=lev[u]+1,q.push(v);
        }
    }
    if(lev[t]!=-1) return true;
    return false; 
}
int dfs1(int u,int flow)
{
    if(u==t) return flow;
    int ret=flow;
    for(int i=head[u];i!=-1;i=nex[i])
    {
        if(ret<=0) break;
        int v=to[i];
        if(cost[i]&&lev[u]+1==lev[v])
        {
            int k=dfs1(v,min(cost[i],ret));
            ret-=k; cost[i]-=k; cost[i^1]+=k; 
        }
    }
    return flow-ret;
}
void dinic()
{
    int ans=0;
    while(bfs()) ans+=(dfs1(s,lie)); 
    printf("%d\n",ans);
}
int main()
{
    freopen("chess.in","r",stdin);
    freopen("chess.out","w",stdout);
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    s=0,t=n*m*4;
    int cnt=0;
    for(ri i=1;i<=n;++i){
        scanf("%s",ss);
        for(ri j=1;j<=m;++j)
        a[i][j]=ss[j-1]-'0',id[i][j]=++cnt;
    }
    hang=0,lie=0;
    for(ri i=1;i<=n;++i)
     for(ri j=1;j<=m;++j)
      if(j==1) h[i][j]=a[i][j] ? 0 : ++hang;
      else if(a[i][j]==a[i][j-1] && a[i][j]==0)
       h[i][j]=h[i][j-1];
      else if(a[i][j-1]==1 && a[i][j]==0)
       h[i][j]=++hang;
      else 
      h[i][j]=0;
    
    for(ri j=1;j<=m;++j)
     for(ri i=1;i<=n;++i)
      if(i==1) l[i][j]=a[i][j] ? 0 : ++lie;
      else if(a[i][j]==a[i-1][j] && a[i][j]==0)
       l[i][j]=l[i-1][j];
      else if(a[i-1][j]==1 && a[i][j]==0)
       l[i][j]=++lie;
      else 
      l[i][j]=0;
    /*for(ri i=1;i<=n;++i){
        for(ri j=1;j<=m;++j)
        cout<<h[i][j]<<" ";
        cout<<endl;
    }
    printf("lie:%d\n",hang);*/
    for(ri i=1;i<=n;++i)
     for(ri j=1;j<=m;++j)
      if(a[i][j]==0)
       add(l[i][j]+n*m,id[i][j],1),add(id[i][j],h[i][j]+2*n*m,1);
    for(ri i=1;i<=lie;++i) add(s,i+n*m,1);
    for(ri i=1;i<=hang;++i) add(i+n*m*2,t,1);
    dinic();
}
/*
3 3
010
001
010
*/
View Code

 

Guess you like

Origin www.cnblogs.com/mowanying/p/11657258.html