线性规划对偶问题 学习笔记

您所在的位置:网站首页 线性规划对偶问题例题讲解及答案 线性规划对偶问题 学习笔记

线性规划对偶问题 学习笔记

2024-06-20 15:11| 来源: 网络整理| 查看: 265

AGC043F

首先排序使得 \(S_{i,1}\le S_{i,2}\le \dots \le S_{i,k_i}\)。

记 \(x_{i,j}\) 表示第 \(i\) 家珠宝店的前 \(j-1\) 种珠宝被选择的次数之和,那么有:

\(0=x_{i,1}\le x_{i,2}\le x_{i,3}\le \dots \le x_{i,k_i+1}=A\)。 \(x_{i,j+1}-x_{i,j}\le c_{i,j}\) 对于限制 \((u_i,v_i,w_i)\),对于 \(\forall j\in[1,k_{v_i}]\),记 \(t\) 为最小的 \(t\) 使得 \(S_{u_i,t}+w_i\ge S_{v_i,j}\),那么如果在珠宝盒 \(v_i\) 选择 \((v_i,j\sim k_{v_i})\),\(u_i\) 珠宝盒只能选择 \(t\sim k_{u_i}\),因此有 \(x_{u_i,t}\le x_{v_i,j}\)。

可以发现以上就是原问题的充要条件,最终要求最小化 \(\sum_{i,j}p_{i,j}(x_{i,j+1}-x_{i,j})\),

与上一个问题基本相同,可以写作以下形式:

\[\min \sum_{i,j}p_{i,j}(x_{i,j+1}-x_{i,j})+\sum_{i,j}\left(+\infty(\max(x_{i,j}-x_{i,j+1},0+\max(x_{i,j+1}-x_{i,j}-c_{i,j},0)\right)+\sum_i\infty x_{i,1}\\ +\sum_i\infty\left(\max(x_{i,k_i+1}-A,0)+\max(A-x_{i,k_i+1},0)\right)+\sum_{u,v,w,j}\infty\max(x_{u,w}-x_{v,j},0) \]

对偶后变成最小费用流,对 \((i,1)\) 的出度减入度要求为 \(+\infty\),其余点要求流量平衡。前 \(2\) 个 \(\sum\) 以及最后一个 \(\sum\) 都正常连边即可,第 \(4\) 个 \(\sum\) 可以看作 \(x_{i,k_i+1}-x_{i,1}-A\),于是相当于从 \((i,1)\) 向 \((i,k_i+1)\) 连流量为 \(+\infty\),费用为 \(A\) 的边;从 \((i,k_i+1)\) 向 \((i,1)\) 连流量为 \(+\infty\),费用为 \(-A\) 的边。因此可以将 \((i,1)\) 作为源点,\((i,k_i+1)\) 向汇点连费用为 \(-A\) 的边,就变成一个最小费用流问题了。

对于多组询问,考虑最终的费用中,\(A\) 只在 \((i,k_i+1)\) 连向汇点的边上作为费用,并且所有连向汇点的边的费用均为 \(-A\),因此最终答案一定形如 \(A\times flow-C\) 的形式,其中 \(flow\) 为流量,\(C\) 为此时其他边的费用。注意到最小费用流的过程形如不断跑最短路,跑出 \(A=0\) 时的 \(dis_t\),如果 \(dis_t\ge A\) 那么就终止,否则将本次增广的流加入答案。因此可以预处理出 \(A=0\) 时每次跑出的 \(dis_t\),以及此时的流量及费用,那么对于每组询问可以通过二分找到对应的 \(flow\) 为多少,即可回答询问。

#include using namespace std; typedef long long ll; const int T=40,M=5e4+10,N=5e3+10,inf=1e9; ll Inf; namespace mcmf{ ll dis[N]; int tot,s,t,first[N],cnt=1,vis[N],cur[N]; struct node{ int u,v,f,nxt;ll c; }e[M*2]; inline void add(int u,int v,int f,ll c){ e[++cnt].u=u;e[cnt].v=v;e[cnt].f=f;e[cnt].c=c; e[cnt].nxt=first[u]; first[u]=cnt; } inline void Add(int u,int v,int f,ll c){ add(u,v,f,c); add(v,u,0,-c); } inline bool SPFA(){ queueq; memset(dis+1,0x3f,sizeof(ll)*(tot)); if(!Inf) Inf=dis[1]; dis[s]=0;vis[s]=1; q.push(s); while(!q.empty()){ int u=q.front();q.pop();vis[u]=0; for(int i=first[u];i;i=e[i].nxt){ int v=e[i].v; if(e[i].f>0&&dis[v]>dis[u]+e[i].c){ dis[v]=dis[u]+e[i].c; if(!vis[v]){vis[v]=1;q.push(v);} } } } return dis[t]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3