zoukankan      html  css  js  c++  java
  • [2018.6.23集训]B-线性规划-最大费用最大流

    题目大意

    给定 $n$ 个待安装软件包。每一个软件包安装所需时间为 $t_i$。
    软件包之间的依赖关系构成了一张 $n$ 个点 $m$ 条边的DAG,一条有向边 $(u->v)$ 代表 $v$ 依赖于 $u$ 。无依赖关系的软件包可以同时安装。
    对于每个软件包,可以花费$c_i$的时间让其 $t_i$ 降低 $1$,可以多次减但不能减为负。
    给定预算 $w$ ,求出安装完这些软件包所需的最短时间。

    $1 leq n leq 55 , 1 leq m leq 400 , 1 leq t_i leq 10^3 , 1 leq c_i leq 10^4, 1 leq w leq 10^9$

    题解

    看着有种网络流的气息。

    考虑二分最后的答案 $ans$,将问题转化为达成当前答案最少需要花费的金额。
    那么可以将问题描述成下列一个线性规划问题:

    设:
    $x_i$ : $i$ 号点被减少的时间
    $A_ij$ : $j$ 号点是否在 $i$ 号路径上(路径数可能是指数级的)
    $b_i$ : $i$ 号路径的长度减去 $ans$

    那么有:

    $ ext{minimize}$ $ c^T x$
    $ ext{S.T.}$ $Ax geq b$
    $ -x geq -t$

    看不出什么问题。
    那么对偶一波。

    $ ext{maximize}$ $ bTy-tTz $
    $ ext{S.T.}$ $ A^Ty -z leq c$

    考虑上面的线性规划的含义。
    这意味着,定义原图中一条路径的收益为其长度减去二分的 $ans$ ,一条路径会覆盖所有其经过点,当一个节点被覆盖超过 $c_i$ 次,需要额外支付 $t_i$ 的代价,最大化最后的收益。

    于是拆点跑费用流即可~

    代码:

    #include<cstdio>
    using namespace std;
    
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0' || '9'<ch){if(ch=='-')f=-1;ch=getchar();}
    	while('0'<=ch && ch<='9')x=x*10+(ch^48),ch=getchar();
    	return x*f;
    }
    
    const int N=59;
    const int M=409;
    const int Inf=1e9+7;
    
    inline bool chkmin(int &a,int b){if(a>b)return a=b,1;return 0;}
    inline bool chkmax(int &a,int b){if(a<b)return a=b,1;return 0;}
    inline int min(int a,int b){return a<b?a:b;}
    
    int n,m,w,s,t;
    int u[M],v[M];
    int ti[N],c[N];
    
    namespace flow
    {
    	const int P=N*2;
    	const int E=P*P*2;
    
    	int to[E],nxt[E],w[E],cost[E],beg[P],tot;
    	int dis[P],q[P],inq[P],mul,ans;
    
    	inline void init()
    	{
    		for(int i=1;i<=t;i++)
    			beg[i]=0;
    		tot=1;ans=0;
    	}
    
    	inline void adde(int u,int v,int c,int d)
    	{
    		to[++tot]=v;
    		nxt[tot]=beg[u];
    		w[tot]=c;
    		cost[tot]=d;
    		beg[u]=tot;
    	}
    
    	inline void add(int u,int v,int c,int d)
    	{
    		adde(u,v,c,d);adde(v,u,0,-d);
    	}
    
    	inline int nxtv(int x){return (x+1)%(P-5);}
    
    	inline bool spfa()
    	{
    		for(int i=1;i<=t;i++)
    			dis[i]=-Inf;
    		dis[t]=0;q[0]=t;
    		for(int l=0,r=1,u=q[l];l!=r;u=q[l=nxtv(l)],inq[u]=0)
    			for(int i=beg[u];i;i=nxt[i])
    				if(w[i^1]>0 && chkmax(dis[to[i]],dis[u]+cost[i^1]) && !inq[to[i]])
    					inq[to[i]]=1,q[r]=to[i],r=nxtv(r);
    		return (mul=dis[s])!=Inf;
    	}
    
    	inline int dfs(int u,int flow)
    	{
    		if(u==t || !flow)return ans+=mul*flow,flow;
    		int costs=0,cdis=dis[u];dis[u]=Inf;
    		for(int i=beg[u],f;i;i=nxt[i])
    			if(w[i]>0 && dis[to[i]]!=Inf && cdis==dis[to[i]]+cost[i])
    			{
    				f=dfs(to[i],min(w[i],flow-costs));
    				w[i]-=f;w[i^1]+=f;costs+=f;
    				if(costs==flow)break;
    			}
    		return costs;
    	}
    
    	inline int lim_mcmf()
    	{
    		while(spfa() && mul>=0)
    			while(dfs(s,Inf));
    		return ans;
    	}
    
    	inline int mcmf()
    	{
    		while(spfa())
    			while(dfs(s,Inf));
    		return ans;
    	}
    }
    
    inline bool check(int x)
    {
    	flow::init();
    	
    	for(int i=1;i<=n;i++)
    	{
    		flow::add(i*2-1,i*2,c[i],ti[i]);
    		flow::add(i*2-1,i*2,Inf,0);
    		flow::add(s,i*2-1,Inf,0);
    		flow::add(i*2,t,Inf,-x);
    	}
    	for(int i=1;i<=m;i++)
    		flow::add(u[i]*2,v[i]*2-1,Inf,0);
    
    	return flow::mcmf()<=w;
    }
    
    int main()
    {
    	n=read();m=read();w=read();
    	for(int i=1;i<=n;i++)
    		ti[i]=read();
    	for(int i=1;i<=n;i++)
    		c[i]=read();
    	for(int i=1;i<=m;i++)
    	{
    		u[i]=read();
    		v[i]=read();
    	}
    
    	s=n*2+1;t=s+1;
    	int l=0,r=1e5,ans=1e9;
    	while(l<=r)
    	{
    		int mid=l+r>>1;
    		if(check(mid))
    			ans=mid,r=mid-1;
    		else
    			l=mid+1;
    	}
    
    	printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    UI第十七讲.图片异步加载(包括第三方), KVO, KVC
    第二十一讲.UICollectionView(集合视图)以及瀑布流效果, 通知中心(NSNotificationCenter).
    UI第十九讲:数据库
    UI第十八讲.初级数据持久化 (沙盒, 简单写入对象, 归解档, NSUserDefaults写入读取文件 )
    第十四讲(下) 可视化方式的实现通讯录.(及storyboard方式)
    第十六讲.网络编程 (HTTP协议)
    wslgit
    MyBatis时间比较
    layer开启与关闭加载层
    MyBatis中choose when正确写法
  • 原文地址:https://www.cnblogs.com/zltttt/p/9286725.html
Copyright © 2011-2022 走看看