[bzoj3532][Sdoi2014]Lis
來(lái)自FallDeram的博客,未經(jīng)允許,請(qǐng)勿轉(zhuǎn)載,謝謝。
?
給定序列A,序列中的每一項(xiàng)Ai有刪除代價(jià)Bi和附加屬性Ci。請(qǐng)刪除若項(xiàng),使得4的最長(zhǎng)上升子序列長(zhǎng)度減少至少1,且付出的代價(jià)之和最小,并輸出方案。如果有多種方案,請(qǐng)輸出將刪去項(xiàng)的附加屬性排序之后,字典序最小的一種。
T<=5 n<=700
?
首先考慮建圖之后最小割 ?每個(gè)點(diǎn)拆成兩個(gè)點(diǎn)中間連費(fèi)用的邊
f[i]表示以i為開(kāi)頭的最長(zhǎng)上升子序列長(zhǎng)度,對(duì)于i<j&&a[i]<a[j]&&f[i]==f[j]+1 從i的出點(diǎn)向j的入點(diǎn)連INF的邊
然后隨意求一個(gè)最小割,按照優(yōu)先級(jí)從小到大考慮每個(gè)點(diǎn)。
一條邊可以被割,當(dāng)且僅當(dāng)這條邊連接了兩個(gè)不同的強(qiáng)聯(lián)通塊。
所以只要一條邊能被割,就把它加入答案,然后把u->S,T->v的流量全部退掉即可。
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #define S 0 #define T 1401 #define INF 2000000000 using namespace std; inline int read() {int x = 0 , f = 1; char ch = getchar();while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();}while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}return x * f; }struct edge{int to,next,w;}e[T*100]; int head[T+5],c[T+5],q[T+5],d[T+5],n,mx,cnt=1,F,a[T+5],b[T+5],top,rk[T+5],C[T+5],f[T+5]; vector<int> ans;inline void ins(int f,int t,int w) {e[++cnt]=(edge){t,head[f],w};head[f]=cnt;e[++cnt]=(edge){f,head[t],0};head[t]=cnt; }bool bfs(int From,int To) {memset(d,0,sizeof(d));int i,j;for(d[q[top=i=1]=From]=1;i<=top;++i)for(int j=c[q[i]]=head[q[i]];j;j=e[j].next)if(e[j].w&&!d[e[j].to])d[q[++top]=e[j].to]=d[q[i]]+1;return d[To]; }int dfs(int x,int To,int f) {if(x==To) return f;int used=0;for(int&i=c[x];i;i=e[i].next)if(e[i].w&&d[e[i].to]==d[x]+1){int w=dfs(e[i].to,To,min(f-used,e[i].w));used+=w;e[i].w-=w;e[i^1].w+=w;if(used==f) return f;}return d[x]=-1,used; } bool cmp(int x,int y){return C[x]<C[y];} int main() {for(int cas=read();cas;--cas){n=read();cnt=mx=1;ans.clear();memset(head,0,sizeof(head));for(int i=1;i<=n;++i) a[i]=read(),rk[i]=i;for(int i=1;i<=n;++i) ins(i,i+n,read());for(int i=1;i<=n;++i) C[i]=read();for(int i=n;i;--i){f[i]=1;for(int j=i+1;j<=n;++j) if(a[j]>a[i])f[i]=max(f[i],f[j]+1);mx=max(mx,f[i]);}for(int i=1;i<=n;++i){if(f[i]==mx) ins(S,i,INF);if(f[i]==1) ins(i+n,T,INF);for(int j=i+1;j<=n;++j)if(a[j]>a[i]&&f[j]==f[i]-1)ins(i+n,j,INF); }F=0;while(bfs(S,T)) F+=dfs(S,T,INF);sort(rk+1,rk+n+1,cmp);for(int i=1;i<=n;++i){int x=rk[i];if(e[x<<1].w||bfs(x,x+n)) continue; e[x<<1].w=e[x<<1|1].w=0;while(bfs(x,S)) dfs(x,S,INF);while(bfs(T,x+n)) dfs(T,x+n,INF);ans.push_back(x);} printf("%d %d\n",F,ans.size());sort(ans.begin(),ans.end());for(int i=0;i<ans.size();++i)printf("%d%c",ans[i],(i+1==ans.size())?'\n':' ');}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/FallDream/p/bzoj3532.html
總結(jié)
以上是生活随笔為你收集整理的[bzoj3532][Sdoi2014]Lis的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: css语法和规则
- 下一篇: 汇编学习笔记(3)-80x86指令集