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;
  }
}

 

posted @ 2019-07-29 22:41  nervending  阅读(564)  评论(3编辑  收藏  举报