zoukankan      html  css  js  c++  java
  • MEX Foundation Contest B

    传送门

    题意

    (m)条边添加进一个二分图中,若第(i)个点度数为(c_i),则其代价为(p_{i,c_i}),不保证(p_i)非降,整个图的代价为所有(2n)个点的代价之和,给定(l,r),请求出最大匹配在([l,r])之间时的最小代价

    (n,mleq 30)

    题解

    夏姬八算

    假设现在的图已经没有增广路了,那么此时的匹配个数就是最大匹配的个数,我们要使其在([l,r])之间

    由于没有增广路,那么我们从每一条匹配边开始跑,会有三种不同的路径

    (1.)开头为右边的点,开头为匹配边,结尾为右边的点,结尾为非匹配边

    (2.)开头为右边的点,开头为匹配边,结尾为左边的点,结尾为匹配边

    (3.)开头为左边的点,开头为匹配边,结尾为左边的点,结尾为非匹配边

    那么每一条匹配边所在的路径一定是上述三种情况之一,所以我们可以把所有的匹配边和非匹配边定向

    先来考虑左边的点,右边的点同样计算

    (f(i,a,b,c,d))表示还需要考虑([i..n])的点,此时向左的非匹配边还剩(a)条,向右的非匹配边还剩(b)条,向右的匹配边还剩(c)条,向左的匹配边还剩(d)条(注意,向左的非匹配边,它的右边对应的点一定是一个匹配点,否则这里就会产生一条增广路,向右的非匹配边同理)

    如果(c>0),那么(i)可以选择连出一条向右的匹配边,那么会有([0,a])条向左的非匹配边连向它

    如果(d>0),那么(i)可以选择连入一条向左的匹配边,那么会有它可以连出([0,b])条向右的非匹配边

    如果不选择连匹配边,那么(i)只能选择有([0,a])条向左的非匹配边连向它(此时这里就是(3)号路径的结尾)

    用记忆化搜索即可

    右边的点同理,不过为了防止(2)号路径被重复计算,我们强制一条从左边开始的路径只能在左边结束(即(3)号路径),一条从右边开始的路径可以任意在左边或右边结束(即(1,2)号路径)

    时间复杂度(O(n^6))

    我觉得可以改一改变成计数题就是了

    //quming
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
    #define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
    template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
    using namespace std;
    typedef long long ll;
    const int N=31;const ll inf=1e18;
    int p[65][35],n,m,l,r;
    ll f[N][N][N][N][N],g[N][N][N][N][N],res;
    ll F(int pos,int a,int b,int c,int d){
    	if(pos==n+1)return !a&&!b&&!c&&!d?0:inf;
    	R ll &res=f[pos][a][b][c][d];
    	if(res<=inf)return res;
    	if(c)fp(i,0,a)cmin(res,F(pos+1,a-i,b,c-1,d)+p[pos][i+1]);
    	if(d)fp(i,0,b)cmin(res,F(pos+1,a,b-i,c,d-1)+p[pos][i+1]);
    	fp(i,0,a)cmin(res,F(pos+1,a-i,b,c,d)+p[pos][i]);
    	return res>=inf?res=inf:res;
    }
    ll G(int pos,int a,int b,int c,int d){
    	if(pos==n+1)return !a&&!b&&!c&&!d?0:inf;
    	R ll &res=g[pos][a][b][c][d];
    	if(res<=inf)return res;
    	if(c)fp(i,1,a)fp(j,0,b)cmin(res,G(pos+1,a-i,b-j,c-1,d)+p[pos+n][i+j+1]);
    	if(d)fp(i,0,b)cmin(res,G(pos+1,a,b-i,c,d-1)+p[pos+n][i+1]);
    	fp(i,0,b)cmin(res,G(pos+1,a,b-i,c,d)+p[pos+n][i]);
    	return res>=inf?res=inf:res;
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	freopen("matching.in","r",stdin);
    	freopen("matching.out","w",stdout);
    	scanf("%d%d%d%d",&n,&m,&l,&r),res=inf;
    	fp(i,1,n<<1)fp(j,0,m)scanf("%d",&p[i][j]);
    	memset(f,0x3f,sizeof(f));
    	memset(g,0x3f,sizeof(g));
    	fp(c,0,r)fp(d,max(0,l-c),r-c)fp(a,0,m-c-d){
    		R int b=m-a-c-d;
    		cmin(res,F(1,a,b,c,d)+G(1,a,b,c,d));
    	}
    	printf("%lld
    ",res);
    	return 0;
    }
    
  • 相关阅读:
    Eclipse启动不了
    第三章Hibernate关联映射
    System Generator简介
    Chipscope使用
    总线及数据传输技术【待完善】
    多相滤波器
    notepad++与ISE/Vivado关联
    常用IP核
    〖Linux〗Qt+gsoap开发客户端程序,服务端地址设定的字符串转换处理
    〖Android〗OK6410a的Android HAL层代码编写笔记
  • 原文地址:https://www.cnblogs.com/yuanquming/p/13154822.html
Copyright © 2011-2022 走看看