[HEOI2016/TJOI2016]游戏

二分图的题

可以分别以行列和列行建

 

1.二分图

#include<bits/stdc++.h>

using namespace std;
const int N=555;

int n,m;
char c[N][N];
int a[N][N],b[N][N];
int flag[N<<5],match[N<<5];
int head[N<<5],nxt[N<<6],to[N<<6];
long long ans;


int _;
void add(int x,int y)
{
    _++;
    to[_]=y;
    nxt[_]=head[x];
    head[x]=_;
    return ;
}

bool find(int x)
{
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        if(!flag[y])
        {
            flag[y]=1; 
            if(!match[y] ||find(match[y]) )
            {
                match[y]=x;
                return 1;
            }    
        }
    }
    
    return 0; 
}
int cnt;
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            cin>>c[i][j];
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(c[i][j]==#)
            {
            cnt++;
            continue;    
            }
            if(j==1)
            cnt++;
            a[i][j]=cnt;
        }
    }
    for (int j=1;j<=m;j++) 
    {
        for (int i=1;i<=n;i++) 
        {
          if(c[i][j]==#) 
              {
                  cnt++;
                  continue;
              }
           if (i==1) cnt++;
           b[i][j]=cnt;
            }
                    
    }
    for (int i=1;i<=n;i++) 
    {
        for (int j=1;j<=m;j++) 
        {
        if(c[i][j]!=*) continue;
        add(a[i][j],b[i][j]);
        }    
        
    }

    for(int i=1;i<=cnt;i++)
    {
        memset(flag,0,sizeof(flag));
        if(find(i))
        ans++;
    }
    cout<<ans;
    
    return 0;
} 

 

2.网络流

#include<bits/stdc++.h>

using namespace std;

const int maxn = 90000;

int tot = -1,n,m,cnt1,cnt2,S,T,ans;
int pos1[60][60],pos2[60][60];
int deep[maxn],head[maxn];
char mp[60][60];
queue<int> q;


struct node
{
    int to,net,va;
}data[maxn<<4];

void add(int a,int b,int c)
{
    data[++tot].net = head[a];data[tot].to = b;data[tot].va = c;head[a] = tot;
    data[++tot].net = head[b];data[tot].to = a;data[tot].va = 0;head[b] = tot;
    return ;
}

bool bfs()
{
    memset(deep,0,sizeof(deep));
    while(!q.empty()) q.pop();
    deep[S] = 1;q.push(S);
    
    while(!q.empty())
    {
        int x = q.front();q.pop();
        for(int i=head[x];i!=-1;i=data[i].net)
        {
            int to = data[i].to ;
            int va = data[i].va ;
            if(va&&!deep[to])
            {
                deep[to] = deep[x] + 1;
                q.push(to);
                if(to==T) return true;
            }
        }
    }
    
    return false;
}

int dfs(int x,int flow)
{
    if(x==T) return flow;
    int rest = flow;
    for(int i=head[x];i!=-1;i=data[i].net)
    {
        int to=data[i].to ;
        int va=data[i].va ;
        if(va&&deep[to]==deep[x]+1)
        {
            int k=dfs(to,min(rest,va));
            if(!k) 
            deep[to]=0;
            data[i].va-=k;data[i^1].va+=k;
            rest-=k;
        }
        
        if(!rest) return flow;
    }
    return flow-rest;
}

int main()
{
    memset(head,-1,sizeof(head));
    cin>>n>>m;
    
    S = n * m + 1;T = n * m + 2;
    for(int i=1;i<=n;i++) 
    scanf("%s",mp[i]+1);
    for(int i=1;i<=n;i++)
    {
        cnt1++;
        for(int j=1;j<=m;j++)
        {
            if(mp[i][j]==#) cnt1++;
            else pos1[i][j]=cnt1;
        }
    }
    for(int j=1;j<=m;j++)
    {
        cnt2++;
        for(int i=1;i<=n;i++)
        {
            if(mp[i][j]==#) cnt2++;
            else pos2[i][j]=cnt2;
        }
    }
    for(int i=1;i<=cnt1;i++) 
    add(S,i,1);
    for(int i=1;i<=cnt2;i++) 
    add(cnt1+i,T,1);
    
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(mp[i][j]==*)
                add(pos1[i][j],pos2[i][j]+cnt1,1);
    while(bfs()) ans += dfs(S,2e9);
    cout<<ans;
    return 0;
}

 

[HEOI2016/TJOI2016]游戏

上一篇:fork & vfork


下一篇:从towSum到nSum