[BZOJ5251][2018多省省队联测]劈配:网络流/最大流

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
const int MAXN=205;
const int MAXM=2405;
int C,n,m,s,t,lim[MAXN],a[MAXN][MAXN],b[MAXN][MAXN][12],exp[MAXN];
int dep[MAXN*2],ans[MAXN],head[MAXN*2],hish[MAXN][MAXN*2],ecnt=-1,hisecnt[MAXN];
struct Edge{
    int frm,to,nxt,cap;
}e[MAXM],hise[MAXN][MAXM*2];
inline void add_edge(int bg,int ed,int ca){
    ecnt++;
    e[ecnt].frm=bg;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].cap=ca;
    head[bg]=ecnt;
    swap(bg,ed);
    ecnt++;
    e[ecnt].frm=bg;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    e[ecnt].cap=0;
    head[bg]=ecnt;
}
inline void delete_edge(int stp){
    while(ecnt>stp){
        head[e[ecnt].frm]=e[ecnt].nxt;
        ecnt--;
    }
}
bool bfs(){
    memset(dep,0x3f,sizeof dep);
    queue<int> q;
    while(!q.empty()) q.pop();
    q.push(s);
    dep[s]=1;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        for(int i=head[u];i!=-1;i=e[i].nxt){
            int ver=e[i].to;
            if(dep[ver]>1e9&&e[i].cap){
                dep[ver]=dep[u]+1;
                q.push(ver);
            }
        }
    }
    return dep[t]<1e9;
}
int dfs(int x,int pref){
    if(!pref||x==t) return pref;
    int flow=0,temp;
    for(int i=head[x];i!=-1;i=e[i].nxt){
        int ver=e[i].to;
        if(dep[ver]==dep[x]+1&&(temp=dfs(ver,min(pref,e[i].cap)))){
            flow+=temp;
            pref-=temp;
            e[i].cap-=temp;
            e[i^1].cap+=temp;
            if(!pref) break;
        }
    }
    return flow;
}
bool check(int x,int y){
    memcpy(head,hish[y-1],sizeof head);
    memcpy(e,hise[y-1],sizeof e);
    ecnt=hisecnt[y-1];
    add_edge(s,x,1);
    for(int i=1;i<=exp[x];i++){
        int prev=ecnt;
        for(int j=1;j<=b[x][i][0];j++)
            add_edge(x,b[x][i][j],1);
        if(bfs()&&dfs(s,1e9)) return 1;
        for(int j=1;j<=b[x][i][0];j++)
            delete_edge(prev);
    }
    return 0;
}
int solve(int x){
    int l=1,r=x-1,rez=0;
    while(l<=r){
        int mid=((l+r)>>1);
        if(check(x,mid)) l=mid+1,rez=mid;
        else r=mid-1;
    }
    return x-rez;
}
int main(){
    int T=read();C=read();
    while(T--){
        memset(b,0,sizeof b);
        memset(ans,0,sizeof ans);
        memset(head,-1,sizeof head);
        ecnt=-1;
        n=read(),m=read();
        s=n+m+1,t=s+1;
        for(int i=1;i<=m;i++){
            lim[i]=read();
            add_edge(n+i,t,lim[i]);
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                a[i][j]=read();
                if(a[i][j])
                    b[i][a[i][j]][++b[i][a[i][j]][0]]=n+j;
            }
        for(int i=1;i<=n;i++)
            exp[i]=read();
        memcpy(hish[0],head,sizeof head);
        memcpy(hise[0],e,sizeof e);
        hisecnt[0]=ecnt;
        for(int i=1;i<=n;i++){
            add_edge(s,i,1);
            int prev=ecnt;
            for(int j=1;j<=m;j++){
                for(int k=1;k<=b[i][j][0];k++)
                    add_edge(i,b[i][j][k],1);
                if(bfs()&&dfs(s,1e9)){
                    ans[i]=j;
                    break;
                }
                for(int k=1;k<=b[i][j][0];k++)
                    delete_edge(prev);
            }
            memcpy(hish[i],head,sizeof head);
            memcpy(hise[i],e,sizeof e);
            hisecnt[i]=ecnt;
        }
        for(int i=1;i<=n;i++)
            printf("%d ",(ans[i]==0?m+1:ans[i]));
        printf("\n");
        for(int i=1;i<=n;i++){
            if(ans[i]&&ans[i]<=exp[i]){
                printf("0 ");
                continue;
            }
            printf("%d ",solve(i));
        }
        printf("\n");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ErkkiErkko/p/9291325.html