hdu6611 2019 多校3K 原始对偶费用流(正权化Dijkstra找增广路)
Posted nervendnig
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu6611 2019 多校3K 原始对偶费用流(正权化Dijkstra找增广路)相关的知识,希望对你有一定的参考价值。
http://acm.hdu.edu.cn/showproblem.php?pid=6611
题很简单,一眼拆点费用流
就是点边拉满之后复杂度有点恐怖,比赛的时候没敢莽费用流
但是最后居然真的是费用流,不过必须上原始对偶且用Dijkstra增广
具体细节很多,大概就是指,原本的Dijktra无法处理负权图,我们就去想办法对所有的费用进行统一扩大,变成正权最短路.
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define rep(ii,a,b) for(int ii=a;ii<=b;++ii) #pragma GCC optimize(2) const int maxn=4e3+30; const int INF=1e9; using namespace std; struct mcfpublic: #define tpp int struct nodeshort to;tpp cap;tpp cost;int rev;; short prev[maxn],pree[maxn]; tpp dis[maxn],cost,h[maxn]; int f; vector<node> g[maxn]; void init(int n=maxn-2)rep(i,0,n+1) g[i].clear(); inline void add(int from,int to,tpp cap,tpp cost) g[from].push_back(to,cap,cost,(int)g[to].size()); g[to].push_back(from,0,-cost,(int)g[from].size()-1); tpp getcost(int s,int t,int flow=INF) f=0,cost=0; fill(h,h+1+t,0); while(flow) #define pdi pair<tpp,short> priority_queue<pdi,vector<pdi>,greater<pdi> >que; fill(dis,dis+t+1,INF); dis[s]=0;que.push(mp(0,s)); while(!que.empty()) auto now=que.top();que.pop(); if(dis[now.se]<now.fi)continue; int x=now.se,cnt=0; for(auto &i:g[x]) if(i.cap>0&&dis[i.to]>dis[x]+h[x]-h[i.to]+i.cost) dis[i.to]=dis[x]+i.cost+h[x]-h[i.to]; prev[i.to]=x,pree[i.to]=cnt++; que.push(mp(dis[i.to],i.to)); else cnt++; if(dis[t]==INF)break; rep(i,0,t+1) h[i]+=dis[i]; tpp d=flow; for(int now=t;now!=s;now=prev[now])d=min(d,g[prev[now]][pree[now]].cap); flow-=d,f+=d;cost+=d*h[t]; for(int now=t;now!=s;now=prev[now]) node &e=g[prev[now]][pree[now]]; e.cap-=d,g[now][e.rev].cap+=d; return cost; net; int casn,n,k,m; int a[maxn/2]; int main() IO; cin>>casn; while(casn--) cin>>n>>k; net.init(n*2+10); int ss=n*2+1,t=n*2+3,s=n*2+2; rep(i,1,n) cin>>a[i]; rep(i,1,n) net.add(i,i+n,1,-a[i]); net.add(ss,i,1,0); net.add(i+n,t,1,0); rep(j,i+1,n) if(a[i]<=a[j]) net.add(i+n,j,1,0); net.add(s,ss,k,0); cout<<-net.getcost(s,t)<<endl;
以上是关于hdu6611 2019 多校3K 原始对偶费用流(正权化Dijkstra找增广路)的主要内容,如果未能解决你的问题,请参考以下文章
[2019多校联考(Round 6 T3)]脱单计划 (费用流)
2019HDU多校第一场 6582 Path 最短路+最大流最小割
HDU-6532 Chessboard 2019广东省省赛B题(费用流)