zoukankan      html  css  js  c++  java
  • BZOJ5251: [2018多省省队联测]劈配

    BZOJ5251: [2018多省省队联测]劈配

    https://lydsy.com/JudgeOnline/problem.php?id=5251

    分析:

    • 这是个水题啊,就是题面太长。
    • 首先要知道这样一件事:
    • 我们建图跑dinic之后若再加一些边跑一次,如果最大流增加,那么一定有新的匹配。
    • 这就意味着不会出现新加的点匹配到了,之前的点却被修改成无匹配状态。
    • 然后按题意模拟即可,第一问直接做,第二问二分。
    • 由于写不明白撤销刚加的边,我每次做的时候都重新建图。

    代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    #define N 405
    #define S 403
    #define T 404
    #define M 1000050
    #define inf 0x3f3f3f3f
    int head[N],to[M],nxt[M],flow[M],cnt,n,m,b[N];
    int dep[N],Q[N],ans1[N],ans2[N],a[N][N],s[N];
    vector<int>V[205][205];
    inline void add(int u,int v,int f) {
        to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; flow[cnt]=f;
        to[++cnt]=u; nxt[cnt]=head[v]; head[v]=cnt; flow[cnt]=0;
    }
    bool bfs() {
        memset(dep,0,sizeof(dep)); dep[S]=1;
        int l=0,r=0;
        Q[r++]=S;
        while(l<r) {
            int x=Q[l++],i;
            for(i=head[x];i;i=nxt[i]) if(!dep[to[i]]&&flow[i]) {
                dep[to[i]]=dep[x]+1; if(to[i]==T) return 1;
                Q[r++]=to[i];
            }
        }
        return 0;
    }
    int dfs(int x,int mf) {
        if(x==T) return mf;
        int i,nf=0;
        for(i=head[x];i;i=nxt[i]) if(dep[to[i]]==dep[x]+1&&flow[i]) {
            int tmp=dfs(to[i],min(mf-nf,flow[i]));
            if(!tmp) dep[to[i]]=0;
            flow[i]-=tmp, flow[i^1]+=tmp, nf+=tmp;
            if(nf==mf) break;
        }
        return nf;
    }
    void dinic() {while(bfs()) while(dfs(S,inf)>0);}
    void solve() {
        scanf("%d%d",&n,&m);
        int i,j,k;
        for(i=1;i<=m;i++) scanf("%d",&b[i]);
        for(i=1;i<=n;i++) for(j=0;j<=m+1;j++) V[i][j].clear();
        memset(ans1,0,sizeof(ans1));
        memset(ans2,0,sizeof(ans2));
        for(i=1;i<=n;i++) {
            for(j=1;j<=m;j++) {
                scanf("%d",&a[i][j]);
                if(a[i][j]) V[i][a[i][j]].push_back(j);
            }
        }
        for(i=1;i<=n;i++) scanf("%d",&s[i]);
        for(i=1;i<=n;i++) {
            memset(head,0,sizeof(head)); cnt=1;
            for(j=1;j<=i;j++) add(S,j,1);
            int bvb=cnt;
            for(j=1;j<=m;j++) add(j+n,T,b[j]);
            for(j=1;j<i;j++) {
                int lim=V[j][ans1[j]].size();
                for(k=0;k<lim;k++) add(j,V[j][ans1[j]][k]+n,1);
            }
            dinic();
            for(j=1;j<=m;j++) {
                int lim=V[i][j].size();
                if(!lim) continue;
                for(k=0;k<lim;k++) {
                    add(i,V[i][j][k]+n,1);
                }
                dinic();
                if(flow[bvb]==1) {
                    ans1[i]=j; break;
                }
            }
            if(!ans1[i]) ans1[i]=m+1;
        }
        for(i=1;i<=n;i++) printf("%d ",ans1[i]); puts("");
        for(i=1;i<=n;i++) {
            if(ans1[i]<=s[i]) continue;
            int l=1,r=i;
            while(l<r) {
                int mid=(l+r)>>1;
                memset(head,0,sizeof(head)); cnt=1;
                int ni=i-mid;
                for(j=1;j<ni;j++) add(S,j,1);
                for(j=1;j<=m;j++) add(j+n,T,b[j]);
                add(S,i,1);
                int bvb=cnt;
                for(j=1;j<ni;j++) {
                    int lim=V[j][ans1[j]].size();
                    for(k=0;k<lim;k++) add(j,V[j][ans1[j]][k]+n,1);
                }
                dinic();
                for(j=1;j<=s[i];j++) {
                    int lim=V[i][j].size();
                    for(k=0;k<lim;k++) add(i,V[i][j][k]+n,1);
                }
                dinic();
                if(flow[bvb]==1) r=mid;
                else l=mid+1;
            }
            ans2[i]=l;
        }
        for(i=1;i<=n;i++) printf("%d ",ans2[i]); puts("");
    }
    int main() {
        int cas;
        scanf("%d%*d",&cas);
        while(cas--) solve();
    }
    
  • 相关阅读:
    安全编码1
    VPP tips
    VPP概述汇总
    C语言安全编码摘录
    TCP-proxy
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.4. Matplotlib: plotting
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.3. NumPy: creating and manipulating numerical data
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.2. The Python language
    Scipy Lecture Notes学习笔记(一)Getting started with Python for science 1.1. Python scientific computing ecosystem
    25马5跑道,求最快的五匹马的需要比赛的次数
  • 原文地址:https://www.cnblogs.com/suika/p/10051103.html
Copyright © 2011-2022 走看看