【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 }
null