[CQOI2009]DANCE跳舞(ISAP写法)

https://daniu.luogu.org/problemnew/show/3153

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>

using namespace std;

#define N 2501
#define M 3001
#define inf 2e9

int n,k;
char s[51];
bool mp[51][51];

int tot;
int front[N],to[M<<1],nxt[M<<1],val[M<<1],from[M<<1];

int src,decc;

int cur[N];

int path[N],num[N],lev[N];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c))  c=getchar(); 
    while(isdigit(c)) { x=x*10+c-'0'; c=getchar();  }
}

void add(int u,int v,int w)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val[tot]=w; from[tot]=u;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; val[tot]=0; from[tot]=v;
    //cout<<u<<' '<<v<<'
';
}

void rebuild(int mid)
{
    tot=1;
    memset(front,0,sizeof(front));
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            if(mp[i][j]) add(i,n*3+j,1);
            else add(n+i,n*2+j,1);
    for(int i=1;i<=n;++i) add(src,i,mid);
    for(int i=1;i<=n;++i) add(n*3+i,decc,mid);
    for(int i=1;i<=n;++i) add(i,n+i,k);
    for(int i=1;i<=n;++i) add(n*2+i,n*3+i,k);
}

bool bfs()
{
    queue<int>q;
    for(int i=src;i<=decc;++i) lev[i]=decc;
    q.push(decc);
    lev[decc]=0;
    int now,t;
    while(!q.empty())
    {
        now=q.front();
        q.pop();
        for(int i=front[now];i;i=nxt[i])
        {
            t=to[i];
            if(lev[t]==decc && val[i^1])
            {
                lev[t]=lev[now]+1;
                q.push(t);
            }
        }
    }
    return lev[src]!=decc;
}

int augment()
{
    int now=decc,flow=inf;
    int i;
    while(now!=src)
    {
        i=path[now];
        flow=min(flow,val[i]);
        now=from[i];
    }
    now=decc;
    while(now!=src)
    {
        val[path[now]]-=flow;
        val[path[now]^1]+=flow;
        now=from[path[now]];
    }
    return flow;
}

int max_flow(int mid)
{
    int flow=0;
    if(!bfs()) return 0;
    memset(num,0,sizeof(num));
    for(int i=src;i<=decc;++i) num[lev[i]]++,cur[i]=front[i];
    int now=src; int t;
    while(lev[src]<=decc)
    {
        if(now==decc)
        {
            flow+=augment();
            now=src;
        }
        int advanced=false;
        for(int i=cur[now];i;i=nxt[i])
        {
            t=to[i];
            if(val[i]>0 && lev[t]==lev[now]-1)
            {
                advanced=true;
                path[t]=i;
                cur[now]=i;
                now=t;
                break;
            }
        }
        if(!advanced)
        {
            int m=decc-1;
            for(int i=front[now];i;i=nxt[i])
                if(val[i]>0) m=min(m,lev[to[i]]);
            if(!--num[lev[now]]) break;
            num[lev[now]=m+1]++;
            cur[now]=front[now];
            if(now!=src) now=from[path[now]];
        }
    }
    return flow;
}

bool check(int mid)
{
    rebuild(mid);
    return max_flow(mid)==n*mid;
}

int main()
{
    read(n); read(k);
    decc=n*4+1;
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s+1);
        for(int j=1;j<=n;++j) mp[i][j]=s[j]=='Y' ? true : false; 
    }
    int l=0,r=n,mid,ans;
    while(l<=r)
    {
        mid=l+r>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1; 
    }
    cout<<ans;
}
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8025120.html