SRM 676 div1 hard
2016-08-22 11:12
423 查看
题目大意
有n种植物,每种植物生长需要ti的时间,当然了,植物可以同时生长。现在有若干条限制xi,yi,表示植物yi要等xi生长完了他才能开始生成长。对于每种植物,可以用ci的代价使其生长时间减1,可以重复使用,但最多减为0。问最少要多少时间所有植物才能长完。n≤50
题解
这题很难。首先假设有两种超级植物S,T,表示S要一开始长,T要最后长。然后我们可以二分答案,设为λ,接下来,对于每种植物,设xi表示他开始长的时间,yi表示他结束生长的时间,di表示减了多少时间。那么可以列出约束⎧⎩⎨⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪⎪ys+λxixtyixi+dixi≥xt≥ys≥yi≥xi≥yi≥yj(j要在i前)
目标函数是
minimize{∑di×ci}
接下来需要考虑一些经典的对偶模型。对于最大循环费用流,其线性规划模型是
⎧⎩⎨⎪⎪fi,j∑jfi,j≥bi,j=∑jfj,imaximize{∑fi,j×costi,j}
这个东西的对偶,就是
vi,j+ϕi−ϕj≥costi,jminimize{∑vi,j×bi,j}
可以发现这个对偶问题貌似能套在原问题上。
比如对于这条式子
yi−xi+di≥ti
是可以直接套的,这相当于在循环流中连上一条xi→yi的流量为ci费用为ti的边。
那么对于类似xi−yj≥0这样的限制,我们只能强行给他加上一个变量p来凑xi−yj+p≥0,但必须满足p=0,相当于在目标函数中p的系数为+∞,那么在循环流中就相当于连上一条yj→xi流量为+∞费用为0的边。
最后的问题是,给定图G,如何求一个最大循环流。
最大循环流
这个问题等价于我们用若干个环,使得其覆盖的权值和最大。一个点在环上,等价于其入度=出度。
那么我们一开始先贪心的把所有权值为正数的边都选上,同时修改两端的度数。对于一条负边权(u,v,f,c),相当于我们可以以c的代价使得deg[u]+1,deg[v]−1,同理,对于一条正边权,我们可以把他删掉,相当于使deg[v]+1,deg[u]−1。最终要使得所有的deg都为0。这就变成了经典的费用流模型了。
代码
#include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 1005; typedef long long ll; class network { public: struct node { ll to,next,flow,cost; node(void){} node(int a,int b,ll c,ll d) : to(a),next(b),flow(c),cost(d){} }e[maxn * 100]; ll deg[maxn]; int final[maxn],ed[maxn][4],n,tot,s,t,cnt; void set(int siz) { n = siz,s = n,t = n + 1; for(int i = 0;i <= t;i ++) final[i] = deg[i] = 0; tot = 1; cnt = 0; } void link(int u,int v,ll f,ll c) { e[++ tot] = node(v,final[u],f,c),final[u] = tot; e[++ tot] = node(u,final[v],0,-c),final[v] = tot; } void push(int u,int v,int f,int c) { ed[++ cnt][0] = u,ed[cnt][1] = v,ed[cnt][2] = f,ed[cnt][3] = c; } ll maxflow() { static ll dis[maxn]; static int pr[maxn]; static bool in[maxn]; ll ret = 0; for(;;) { for(int i = 0;i <= t;i ++) dis[i] = (1ll << 60),in[i] = 0; dis[s] = 0; static int que[maxn * 100]; que[1] = s; in[s] = 1; for(int fi = 1,en = 1;fi <= en;fi ++) { int u = que[fi]; for(int i = final[u];i;i = e[i].next) if (e[i].flow > 0 && dis[e[i].to] > dis[u] + e[i].cost) { dis[e[i].to] = dis[u] + e[i].cost; pr[e[i].to] = i; if (!in[e[i].to]) { in[e[i].to] = 1,que[++ en] = e[i].to; } } in[u] = 0; } if (dis[t] == (1ll << 60)) break; ll fl = (1ll << 60); for(int i = t;i != s;i = e[pr[i] ^ 1].to) fl = min(fl,e[pr[i]].flow); ret += fl * dis[t]; for(int i = t;i != s;i = e[pr[i] ^ 1].to) e[pr[i]].flow -= fl,e[pr[i] ^ 1].flow += fl; } return ret; } ll calc() { ll sum = 0; for(int i = 1;i <= cnt;i ++) { ll u = ed[i][0],v = ed[i][1],f = ed[i][2],c = ed[i][3]; if (c < 0) link(u,v,f,-c); else { sum += f * c; deg[u] += f,deg[v] -= f; link(v,u,f,c); } } for(int i = 0;i < n;i ++) if (deg[i] < 0) link(s,i,-deg[i],0); else link(i,t,deg[i],0); return sum - maxflow(); } }flow; class Farmville { public: int minTime(vector<string> s, vector<int> t, vector<int> c,int budget) { int l = 0,r = 100000,tmp,n = t.size(); for(int mid;l <= r;) { mid = l + r >> 1; flow.set(n * 2 + 2); int ys = n * 2,xt = n * 2 + 1; for(int i = 0;i < n;i ++) { flow.push(ys,i << 1,1 << 30,0),flow.push(i << 1 | 1,xt,1 << 30,0); flow.push(i << 1,i << 1 | 1,1 << 30,0),flow.push(i << 1,i << 1 | 1,c[i],t[i]); } for(int i = 0;i < n;i ++) for(int j = 0;j < n;j ++) if (s[i][j] == '1') flow.push(j << 1 | 1,i << 1,1 << 30,0); flow.push(xt,ys,1 << 30,-mid); if (flow.calc() > budget) l = mid + 1; else tmp = mid,r = mid - 1; } return tmp; } };
相关文章推荐
- [LP对偶费用流] SRM 676 div1 Farmville
- SRM 683 div1 hard
- Topcoder SRM 505 Div 2 hard
- DP SRM 661 Div2 Hard: ColorfulLineGraphsDiv2
- Topcoder SRM 676 div2
- [DP] Topcoder SRM 552 DIV1 Hard. HolyNumbers
- [期望DP] SRM 579 Div1 Hard RockPaperScissors
- [LP对偶][含正权环的最大费用流] SRM 676 div1 1000pts Farmville
- [拉格朗日插值]SRM 683 Div1 Hard RandomWalkOnGrid
- Topcoder SRM 663 Div2 Hard: CheeseRolling(状压DP)
- [容斥 DP] Topcoder SRM 498 DIV1 Hard. FoxJumping
- SRM 664 Div2 Hard: BearSortsDiv2(归并排序)
- 埃氏筛法+快速幂+dp SRM 660 Div 2 Hard: Powerit
- [DP] SRM 452 Div1 Hard IncreasingNumber
- 将一个带有‘?’的数拆解成两个由4-7组成的数,求该数最小值 回溯法 数学 SRM 665 Div2 Hard LuckySum
- [容斥原理][复杂度分析] SRM 555 Div1 Hard MapGuessing
- [矩阵树定理 容斥 meet in middle] Topcoder SRM 551 DIV1 Hard. SweetFruits
- [DP][拉格朗日插值][生成函数] SRM 629 Div1 Hard CandyDrawing
- TopCoder SRM 710 Div2 Hard MinMaxMax Floyd最短路变形
- TC SRM 636 Div2 C ChocolateDividingHard 二分