zoukankan      html  css  js  c++  java
  • 杂题

    题意

    给定一个带边权的(K_{n,n}),边权表示为({a_{i,j}})
    (q)次询问,每次给定(C)
    为左部和右部点分别设置一个顶标({x_i},{y_i})
    你要格外确定一个花费(S),使得(forall i,j, ext{s.t.} x_i+y_jge a_{i,j}-frac{S}{C}),最小化(sum x_i+sum y_i+S)
    顶标与花费均为非负实数。
    (Nle 500,a_{i,j}in[0,10^9],Cin (0,10^9])

    做法

    写成线性规划的形式:

    [egin{aligned} & ext{minimize} sum x_i+sum y_i+S\ & ext{s.t.}egin{cases} x_i+y_j+frac{S}{C}ge a_{i,j}&(1le i,jle n)\ x_ige 0,y_ige 0,Sge 0 end{cases} end{aligned}]

    (z=frac{S}{C})

    [egin{aligned} & ext{minimize} sum x_i+sum y_i+Ccdot z\ & ext{s.t.}egin{cases} x_i+y_j+zge a_{i,j}&(1le i,jle n)\ x_ige 0,y_ige 0,zge 0 end{cases} end{aligned}]

    写成对偶的形式:

    [egin{aligned} & ext{maximize} sumlimits_{i=1}^n sumlimits_{j=1}^n a_{i,j}x_{i,j}\ & ext{s.t.}egin{cases} sumlimits_{j=1}^n x_{i,j}le 1&(1le ile n)\ sumlimits_{i=1}^n x_{i,j}le 1&(1le jle n)\ sumlimits_{i=1}^n x_{i,j}le C\ x_{i,j}ge 0\ end{cases} end{aligned}]

    可以看作是二分图匹配:将(x_{i,j})值域定义为({0,1}),感性理解挺对的。

    然后就是限制匹配数为(C)的最大权二分图匹配。

    可以用KM实现

    code

    放份板子

    #include<bits/stdc++.h>
    typedef long long LL;
    typedef double dl;
    #define opt operator
    #define pb push_back
    #define pii std::pair<LL,LL>
    const LL maxn=509,mod=998244353,inf=1e9;
    LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0' && c<='9'){
    		x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
    	}return x*f;
    }
    void Chkmin(LL &x,LL y){
    	if(y<x) x=y;
    }
    void Chkmax(LL &x,LL y){
    	if(y>x) x=y;
    }
    LL add(LL x,LL y){
    	return x+=y,x>=mod?x-mod:x;
    }
    LL dec(LL x,LL y){
    	return x-=y,x<0?x+mod:x;
    }
    LL mul(LL x,LL y){
    	return 1ll*x*y%mod;
    }
    LL Pow(LL base,LL b){
    	LL ret(1); while(b){
    		if(b&1) ret=mul(ret,base); base=mul(base,base); b>>=1;
    	}return ret;
    }
    LL n,q;
    LL pre[maxn],a[maxn][maxn],ans[maxn],mtx[maxn],mty[maxn],vall[maxn],valr[maxn];
    void Revese(LL y){
    	while(y){
    		LL x(pre[y]); LL tmp(mty[x]);
    		mty[x]=y; mtx[y]=x;
    		y=tmp;
    	}
    }
    void Bfs(){
    	static LL markx[maxn],marky[maxn],slack[maxn];
    	for(LL i=1;i<=n;++i){
    		markx[i]=marky[i]=pre[i]=0;
    		slack[i]=inf;
    	}
    	std::queue<LL> que;
    	for(LL i=1;i<=n;++i) if(!mty[i]){
    		que.push(i);
    	}
    	while(true){
    		while(que.size()){
    			LL u(que.front()); que.pop();
    			markx[u]=1;
    			for(LL i=1;i<=n;++i) if(!marky[i]){
    				LL gap(vall[u]+valr[i]-a[u][i]);
    				if(gap<slack[i]){
    					pre[i]=u;
    					slack[i]=gap;
    					if(!gap){
    						if(!mtx[i]){
    							Revese(i); return;
    						}else{
    							marky[i]=1;
    							que.push(mtx[i]);
    						}
    					}
    				}
    			}
    		}
    		LL d(inf),pos(0);
    		for(LL i=1;i<=n;++i) if(!marky[i]){
    			if(slack[i]<d){
    				pos=i; d=slack[i];
    			}
    		}
    		for(LL i=1;i<=n;++i){
    			if(markx[i]) vall[i]-=d;
    			if(marky[i]) valr[i]+=d;
    			else slack[i]-=d;
    		}
    		if(!mtx[pos]){
    			Revese(pos); return;
    		}
    		marky[pos]=1;
    		que.push(mtx[pos]);
    	}
    }
    void Fir(){
    	for(LL i=1;i<=n;++i){
    		vall[i]=1e9;
    	}
    	for(LL i=1;i<=n;++i){
    		valr[i]=0;
    	}
    	for(LL i=1;i<=n;++i){
    		Bfs();
    		for(LL j=1;j<=n;++j){
    			if(mty[j]){
    				ans[i]+=a[j][mty[j]];
    			}
    		}
    	}
    }
    int main(){
    	LL tmp(Read());
    	n=Read(); q=Read();
    	for(LL i=1;i<=n;++i){
    		for(LL j=1;j<=n;++j){
    			a[i][j]=Read();
    		}
    	}
    	Fir();
    	while(q--){
    		LL C(Read());
    		printf("%lld.0
    ",ans[std::min(C,n)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    springmvc乱码问题
    51nod 还是01串
    51nod 1276 岛屿的数量
    poj 2486 a apple tree
    hdu 1011 Starship Troopers
    poj 1155 TELE
    hdu 4586 Play the Dice
    hdu 5023 A Corrupt Mayor's Performance Art(线段树水题)
    Appleman and Tree
    hdu 4003
  • 原文地址:https://www.cnblogs.com/Grice/p/14509486.html
Copyright © 2011-2022 走看看