【HDOJ6611】K Subsequence(费用流)

题意:给定一个长为n的正整数序列,要求从中取出至多k个不下降序列,使得它们的和最大,求这个和

n<=2e3,k<=10,a[i]<=1e5

思路:极其考验模板,反正我的spfa和zkw都挂了,就拿这题std做dijkstra费用流的板子了

 

 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef pair<int,int> PII;
  7 typedef pair<ll,ll> Pll;
  8 typedef vector<int> VI;
  9 typedef vector<PII> VII;
 10 typedef pair<ll,ll>P;
 11 #define N  10000
 12 #define M  2100000
 13 #define fi first
 14 #define se second
 15 #define MP make_pair
 16 #define pb push_back
 17 #define pi acos(-1)
 18 #define mem(a,b) memset(a,b,sizeof(a))
 19 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 20 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 21 #define lowbit(x) x&(-x)
 22 #define Rand (rand()*(1<<16)+rand())
 23 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 24 #define ls p<<1
 25 #define rs p<<1|1
 26 
 27 const int MOD=998244353,inv2=(MOD+1)/2;
 28       double eps=1e-4;
 29       int INF=0x7fffffff;;
 30       ll inf=5e13;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 struct edge
 35 {
 36     int to,cap,cost,rev;
 37     edge(){}
 38     edge(int a,int b,int c,int d):
 39     to(a),cap(b),cost(c),rev(d){}
 40 };
 41 
 42 int read()
 43 {
 44    int v=0,f=1;
 45    char c=getchar();
 46    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 47    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 48    return v*f;
 49 }
 50 
 51 struct MCMF
 52 {
 53     int V,h[N],dis[N],preV[N],preE[N];
 54     vector<edge> g[N];
 55 
 56     void init(int n)
 57     {
 58         V=n;
 59         rep(i,0,V) g[i].clear();
 60     }
 61 
 62     void add(int u,int v,int cap,int cost)
 63     {
 64         g[u].pb(edge(v,cap,cost,g[v].size()));
 65         g[v].pb(edge(u,0,-cost,g[u].size()-1));
 66     }
 67 
 68     int minc_mf(int S,int T,int f,int &flow)
 69     {
 70         int res=0;
 71         fill(h,h+1+V,0);
 72         while(f)
 73         {
 74             priority_queue <PII,vector<PII>, greater<PII> > q;
 75             fill(dis,dis+1+V,INF);
 76             dis[S]=0;
 77             q.push(MP(0,S));
 78             while(!q.empty())
 79             {
 80                 PII now=q.top(); q.pop();
 81                 int u=now.se;
 82                 if(dis[u]<now.fi) continue;
 83                 for(int i=0;i<g[u].size();i++)
 84                 {
 85                     edge e=g[u][i];
 86                     int v=e.to;
 87                     if(e.cap>0&&dis[v]>dis[u]+e.cost+h[u]-h[v])
 88                     {
 89                         dis[v]=dis[u]+e.cost+h[u]-h[v];
 90                         preV[v]=u;
 91                         preE[v]=i;
 92                         q.push(MP(dis[v],v));
 93                     }
 94 
 95                 }
 96             }
 97             if(dis[T]==INF) break;
 98             rep(i,0,V) h[i]+=dis[i];
 99             int t=f,k=T;
100             while(k!=S)
101             {
102                 int e=preE[k];
103                 t=min(t,g[preV[k]][preE[k]].cap);
104                 k=preV[k];
105             }
106             f-=t; flow+=t; res+=t*h[T];
107             k=T;
108             while(k!=S)
109             {
110                 edge &e=g[preV[k]][preE[k]];
111                 e.cap-=t;
112                 g[k][e.rev].cap+=t;
113                 k=preV[k];
114             }
115         }
116         return res;
117     }
118 }mcmf;
119 
120 int num[N][2],a[N],S,T,s,flow;
121 
122 int main()
123 {
124     int cas=read();
125     s=0;
126     while(cas--)
127     {
128         int n=read(),k=read();
129         rep(i,1,n) a[i]=read();
130         s=0;
131         rep(i,1,n)
132         {
133             num[i][0]=++s;
134             num[i][1]=++s;
135         }
136         S=++s; s++; T=++s;
137         mcmf.init(s);
138         mcmf.add(S,S+1,k,0);
139         rep(i,1,n) mcmf.add(S+1,num[i][0],1,0);
140         rep(i,1,n) mcmf.add(num[i][0],num[i][1],1,-a[i]);
141         rep(i,1,n)
142          rep(j,i+1,n)
143           if(a[j]>=a[i]) mcmf.add(num[i][1],num[j][0],1,0);
144         rep(i,1,n) mcmf.add(num[i][1],T,1,0);
145         flow=0;
146         int ans=-mcmf.minc_mf(S,T,INF,flow);
147         printf("%d\n",ans);
148     }
149     return 0;
15nb0 }

 无敌zyd的优化建图,思路是每个i都只与后面有可能构成最优解的j连边,最坏情况下没有任何改进,但好像因为a[i]是随机数据跑的飞快

  1 #pragma GCC optimize("O3")
  2 #pragma G++ optimize("O3")
  3 #include <queue>
  4 #include <cstdio>
  5 #include <cstring>
  6 #include <iostream>
  7 #include <algorithm>
  8 #define rep(i,l,r) for(int i=l;i<=r;++i)
  9 #define per(i,l,r) for(int i=l;i>=r;--i)
 10 using namespace std;
 11 
 12 
 13 const int N = 10000, M=100000;
 14 const int INF = 1e9;
 15 int n,m;
 16 int a[M];
 17 
 18 struct EG {
 19     int a, b, c, d, e;
 20 } eg[M];
 21 int head[N], en, S, T, SS;
 22 int flow, cost;
 23 int dis[N], pre[N], rem[N];
 24 bool inq[N];
 25 void insert(int u, int v, int w, int z) {
 26     eg[++en] = (EG) {v, head[u], w, z, u}; head[u] = en;
 27     eg[++en] = (EG) {u, head[v], 0, -z, v}; head[v] = en;
 28 }
 29 void Clear() {
 30     memset(head, 0, sizeof head);
 31     en = 1;
 32 }
 33 bool Spfa() {
 34     for (int i = 1; i <= SS; i++) dis[i] = INF, inq[i] = 0;
 35     dis[S] = 0;
 36     inq[S] = 1;
 37     queue<int> Q; Q.push(S);
 38     pre[S] = 0, rem[S] = INF;
 39     while (!Q.empty()) {
 40         int u = Q.front(); Q.pop();
 41         inq[u] = 0;
 42         for (int e = head[u]; e; e = eg[e].b) {
 43             int v = eg[e].a;
 44             if (eg[e].c > 0 && dis[u] + eg[e].d < dis[v]) {
 45                 dis[v] = dis[u] + eg[e].d;
 46                 pre[v] = e;
 47                 rem[v] = min(rem[u], eg[e].c);
 48                 if (!inq[v]) {
 49                     inq[v] = 1;
 50                     Q.push(v);
 51                 }
 52             }
 53         }
 54     }
 55     if (dis[T] == INF) return 0;
 56     flow += rem[T];
 57     cost += dis[T] * rem[T];
 58     int u = T;
 59     while (u != S) {
 60         eg[pre[u]].c -= rem[T];
 61         eg[pre[u] ^ 1].c += rem[T];
 62         u = eg[pre[u]].e;
 63     }
 64     return 1;
 65 }
 66 void MinCost() {
 67     flow = cost = 0;
 68     while (Spfa());
 69 }
 70 
 71 int main() {
 72     //freopen("a.txt","r",stdin);
 73 
 74     int test_;
 75     cin>>test_;
 76     while (test_--) {
 77         scanf("%d%d",&n,&m);
 78         rep(i,1,n) scanf("%d",a+i);
 79 
 80 
 81         Clear();
 82         S = n * 2 + 10, T = S + 1, SS = T + 1;
 83         for (int i = 1; i <= n; i++)
 84         {
 85             insert(i, i + n, 1, -a[i]);
 86             insert(i, i + n, m, 0);
 87             int mx = INF;
 88             for (int j = i + 1; j <= n; j++)
 89             {
 90                 if (a[j] < mx && a[j] >= a[i])
 91                 {
 92                     insert(i + n, j, INF, 0);
 93                     mx = a[j];
 94                 }
 95             }
 96         }
 97         insert(S, SS, m, 0);
 98         for (int i = 1; i <= n; i++)
 99         {
100             insert(SS, i, 1, 0);
101             insert(i + n, T, 1, 0);
102         }
103         MinCost();
104         printf("%d\n", -cost);
105     }
106 }

 

posted on 2019-09-29 16:47  myx12345  阅读(210)  评论(0编辑  收藏  举报

导航