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

bzoj
luogu

sol

从前往后依次加边,每次对一个人做完劈配后就把当前这个残余网络存下来。这样第二问就可以二分排在第几名然后check一下在对应排名的残余网络上还能不能再增广。
给网络流开结构体直接赋值美滋滋。
然后这样就可以根据评测机的实际情况获得\(60-80\)不等的好成绩。
一个显而易见的优化就是:对于一个人,如果他已经确认了选择某个志愿,那么不仅更靠后的志愿是没用的,更靠前的志愿也是没用的。
所以对于一个人我们只需要保留他选的那个志愿对应的那至多\(C\)条边,这样边数和时间复杂度都降下来了。
按照上面的思路就可以成功通过本题了。

code

#include
#include
#include
#include
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int inf = 1e9;
const int N = 405;
int n,m,S,T,a[N][N],b[N],id[N],s[N],ans[N];
queueQ;
struct edge{int to,nxt,w;};
struct net{
    edge a[N*30];
    int head[N],cnt,dep[N],cur[N];
    inline void init(){memset(head,0,sizeof(head));cnt=1;}
    inline void link(int u,int v,int w)
        {
            a[++cnt]=(edge){v,head[u],w};head[u]=cnt;
            a[++cnt]=(edge){u,head[v],0};head[v]=cnt;
        }
    inline bool bfs()
        {
            memset(dep,0,sizeof(dep));
            dep[S]=1;Q.push(S);
            while (!Q.empty())
            {
                int u=Q.front();Q.pop();
                for (int e=head[u];e;e=a[e].nxt)
                    if (a[e].w&&!dep[a[e].to])
                        dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
            }
            return dep[T];
        }
    int dfs(int u,int f)
        {
            if (u==T) return f;
            for (int &e=cur[u];e;e=a[e].nxt)
                if (a[e].w&&dep[a[e].to]==dep[u]+1)
                {
                    int tmp=dfs(a[e].to,min(a[e].w,f));
                    if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}
                }
            return 0;
        }
    inline int dinic()
        {
            int res=0;
            while (bfs())
            {
                for (int i=1;i<=T;++i) cur[i]=head[i];
                while (int tmp=dfs(S,1)) res+=tmp;
            }
            return res;
        }
}G[N>>1];
inline bool cmp(int i,int j){return b[i]>1;
                net tmp=G[mid];tmp.link(S,i,1);
                for (int j=1;j<=m;++j) if (a[i][j]&&a[i][j]<=s[i]) tmp.link(i,j+n,1);
                if (tmp.dinic()) res=l=mid+1;else r=mid-1;
            }
            printf("%d ",i-res);
        }
        puts("");
    }
    return 0;
}

转载于:https://www.cnblogs.com/zhoushuyu/p/8761192.html

你可能感兴趣的:([BZOJ5251][多省联测2018]劈配)