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题(费用流)

[2020杭电多校第二场]1005 New Equipments(费用流)

bzoj3112: [Zjoi2013]防守战线