P3153 [CQOI2009] dance bipartite network flow

  

Title Description

A dance there are n boys and n girls. Every song begins, all just boys and girls paired n of ballroom dancing. Every boy and not a girl jump with two (or more) dance. There are some boys and girls like each other, while others do not like each other (not "one-way love"). Every boy only comfortable and the k do not like dancing girls, each girl only comfortable and k-boy does not like to dance. Whether the information is given every boy and girl like each other, you can have up to dance a few dance track?

Input Format

The first line contains two integers n and k. The following n lines each containing n characters, where the i-th row j-th character 'Y' if and only if i boys and girls like each j.

Output Format

Only a few, i.e. the maximum number of dance.

Sample input and output

Input # 1
3 0
YYY
YYY
YYY
Output # 1
3


1. be dancing

Since I can not look at dry, then a dance, everyone had to jump, in other words, if the answer to this question ans, then eventually everyone can just hop dance ans,

So we dichotomous answers, run at a maximum flow model, and finally check the answers, if the condition is satisfied :( total number of dance is ans * N (number)) we have up search, or to search down, shrinking half range find the answer (In fact, the range of data seemingly direct enumeration)

2. The same person will not dance

Basics match, even men and women side capacity of 1 can not be repeated

3. Can the k and do not like to dance

The number of games we can dance the requirements of the most naturally wanted as little more than k, while k can not be changed, but according to the greedy thoughts, we can not just try to do k k, in other words, if the partner and love each other, they do not k is the number of times consumed.

In order to achieve mutual love of dancing people do not consume k, we need to split the point: Each male / female split into two parts of likes and dislikes, and even the edges as shown below

a dichotomous answer out of the source point for the men and a capacity to ensure that a person can jump a field of dance, as well as answers to the maximum flow verification (dark is like a light that is not like)

If two people love each other, there are:

Such a direct link like the way s to t is unoccupied k, k number that is no consumption; capacity of 1 to ensure that the same person and only jump once dance


If the two do not like each other, there

不喜欢的人跳舞不愿意,需要消耗k,路径被夹在k之间,最大流从之间通过消耗k,达到目的;容量为1同样保证了只和同一人跳一次舞

 
  
#include<bits/stdc++.h>
using namespace std;
//input by bxd
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define RI(n) scanf("%d",&(n))
#define RII(n,m) scanf("%d%d",&n,&m)
#define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define RS(s) scanf("%s",s);
#define ll long long
#define pb push_back
#define REP(i,N)  for(int i=0;i<(N);i++)
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
#define inf 0x3f3f3f3f
const int N=4e5+44;
const int M=4e6+54;
int d[N];
struct edge {
    int to, next, w;
} e[M << 1];
int head[N],cur[N],cnt = 1;
void add(int x, int y, int z) {
    e[++cnt] = (edge){y, head[x], z};
    head[x] = cnt;
    e[++cnt] = (edge){x, head[y], 0};
    head[y] = cnt;
}
void init()
{
    cnt=1;CLR(head,0);CLR(cur,0);
}
void ins(int x,int y,int a,int b)
{
    add(x,y,b-a);
    d[x]-=a;
    d[y]+=a;
}

int level[N];
bool bfs(int s, int t) {
    memset(level, 0, sizeof level);
    queue<int> q;
    level[s] = 1;
    q.push(s);
    while (!q.empty()) {
        int pos = q.front();q.pop();
        for (int i = head[pos]; i; i = e[i].next) {
            int nx = e[i].to;
            if (!e[i].w || level[nx]) continue;
            level[nx] = level[pos] + 1;
            q.push(nx);
        }
    }
    return level[t];
}
int dfs(int s, int t, int flow) {
    if(s==t||flow==0)return flow;

    int f,ret = 0;
    for (int &i = cur[s],v; i; i = e[i].next) {
         v = e[i].to;
        if (level[v] == level[s] + 1 && (f=dfs(v,t,min(flow,e[i].w)))>0) {
            e[i].w -= f;
            e[i ^ 1].w += f;
            flow -= f;
            ret += f;
            if(!flow)break;
        }
    }
    return ret;
}
int dinic(int s, int t) {
    int ret = 0;
    while (bfs(s, t)) memcpy(cur,head,sizeof cur),ret += dfs(s, t, inf);
    return ret;
}
int n,m,s,t,a,b,c,sum,S,T,k;
char mp[100][100];

void build(int a)
{
    init();
    rep(i,1,n)
    {
        add(s,i,a);
        add(i,i+n,k);
        add(i+2*n,i+3*n,k);
        add(i+3*n,t,a);
    }
    rep(i,1,n)
    rep(j,1,n)
    {
        if(mp[i][j]=='Y')add(i,j+3*n,1);
        else add(i+n,j+2*n,1);
    }
}

bool check(int x)
{
    build(x);
    return dinic(s,t)==n*x;
}

int main()
{
    scanf("%d%d",&n,&k);s=10*n+1,t=s+1;
    rep(i,1,n){scanf("%s",mp[i]+1);}


    int L=0,R=n,ans=0;
    while(L<=R)
    {
        int mid=(L+R)>>1;
        if(check(mid))L=mid+1,ans=mid;
        else R=mid-1;
    }
    cout<<ans;
    return 0;
}
View Code

 





Guess you like

Origin www.cnblogs.com/bxd123/p/11311310.html