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 mcf{public:
  #define tpp int
  struct node{short 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;
  }
}

原文地址:https://www.cnblogs.com/nervendnig/p/11267010.html

时间: 2024-08-28 23:56:47

hdu6611 2019 多校3K 原始对偶费用流(正权化Dijkstra找增广路)的相关文章

【BZOJ-3638&amp;3272&amp;3267&amp;3502】k-Maximum Subsequence Sum 费用流构图 + 线段树手动增广

3638: Cf172 k-Maximum Subsequence Sum Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 174  Solved: 92[Submit][Status][Discuss] Description 给一列数,要求支持操作: 1.修改某个数的值 2.读入l,r,k,询问在[l,r]内选不相交的不超过k个子段,最大的和是多少. Input The first line contains integer n (1 ≤ n 

2019雅礼集训 D4T1 w [费用流]

题目描述: 样例: input1: 4 1 2 1 2 3 4 1 2 1 3 3 4 1 2 2 3 1 4 2 1 3 4 1 1 2 3 output1: 9 input2: 5 1 1 3 99 99 100 2 1 2 1 3 3 4 3 5 1 3 1 2 2 4 2 5 2 1 2 3 1 2 1 2 2 1 output2: 198 数据范围: 先放个原题地址:CF1061E. 毒瘤出题人搬原题差评 毒瘤出题人题目翻译出锅差评 这题看到如此不伦不类的问法,似乎不是dp.贪心等算法

codevs1028花店橱窗布置(费用流)

这几天刚学了费用流,找到了这道题来练一练手. 题目: 题目描述 Description 假设以最美观的方式布置花店的橱窗,有F束花,V个花瓶,我们用美学值(一个整数)表示每束花放入每个花瓶所产生的美学效果.为了取得最佳的美学效果,必须使花的摆放取得最大的美学值. 输入描述 Input Description 第一行为两个整数F,V(F<=V<=100) 接下来F行每行V个整数,第i行第j个数表示第i束花放入第j个花瓶的美学值. 输出描述 Output Description 一个整数,即最大美

让菜鸡讲一讲费用流(EK)

让我再讲一个故事吧. 又有一些小精灵要准备从银月城(S)迁徙到Nibel山(T). 这两个地方之间的道路构成了一个网络. 每个道路都有它自己的容量,这决定了每天有多少小精灵可以同时从这儿通过. 和上一篇不同的是,由于上次迁徙的规模很大, 吸引了其它一些种族的注意, 这次每条道路都会有一些人/兽人/哥布林/...向精灵们征收过路费, 现在精灵们想知道,在花费最小的情况下,它们迁徙的速度最大是多少只每天. 费用流=最小费用最大流 在要求流最大的情况下要求费用最小,好像原来的isap已经派不上用场了呢

网络流板子/费用流板子 2018南京I题+2016青岛G题

2018南京I题: dinic,链式前向星,数组队列,当前弧优化,不memset全部数组,抛弃满流点,bfs只找一条增广路,每次多路增广 #include <bits/stdc++.h> #define ll long long #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) using namespace std; con

HDU 2686 Matrix(最大费用流)

Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1890    Accepted Submission(s): 1005 Problem Description Yifenfei very like play a number game in the n*n Matrix. A positive integer numbe

【进阶——最小费用最大流】hdu 1533 Going Home (费用流)Pacific Northwest 2004

题意: 给一个n*m的矩阵,其中由k个人和k个房子,给每个人匹配一个不同的房子,要求所有人走过的曼哈顿距离之和最短. 输入: 多组输入数据. 每组输入数据第一行是两个整型n, m,表示矩阵的长和宽. 接下来输入矩阵. 输出: 输出最短距离. 题解: 标准的最小费用最大流算法,或者用KM算法.由于这里是要学习费用流,所以使用前者. 最小费用最大流,顾名思义,就是在一个网络中,不止存在流量,每单位流量还存在一个费用.由于一个网络的最大流可能不止一种,所以,求出当前网络在流量最大的情况下的最小花费.

HDU 2485 Destroying the bus stations(费用流)

http://acm.hdu.edu.cn/showproblem.php?pid=2485 题意: 现在要从起点1到终点n,途中有多个车站,每经过一个车站为1时间,现在要在k时间内到达终点,问至少要破坏多少个车站. 思路: 把每个点拆分为两个点,容量为1,费用为0.之后相邻的车站连边,容量为INF,费用为1,表示经过一个车站需要1时间. 这样一来,跑一遍费用流计算出在费用不大于k的情况下的最大流,也就是最小割,即至少要破坏的车站数. 在网络中寻求关于f的最小费用增广路,就等价于在伴随网络中寻求

【BZOJ4514】[Sdoi2016]数字配对 费用流

[BZOJ4514][Sdoi2016]数字配对 Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在获得的价值总和不小于 0 的前提下,求最多进行多少次配对. Input 第一行一个整数 n. 第二行 n 个整数 a1.a2.…….an. 第三行 n 个整数 b1.b2.