當前位置:
首頁 >
P2766-最长不下降子序列问题【网络流,dp】
發布時間:2023/12/3
36
豆豆
生活随笔
收集整理的這篇文章主要介紹了
P2766-最长不下降子序列问题【网络流,dp】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
求最長不下降子序列和可以取出多少以及允許多次使用一些數時可以取出多少個。
解題思路
第一問dp求,且保存以xxx開頭的最長長度fxf_xfx?。
第二問考慮網絡流。
我們對于每個數字以fif_ifi?的不同分層,然后每次從下往上一層連接,然后對于每個點拆開以限制每個點的流量保證每個點只取一次就好了。
第三問在第二問的基礎上將點1和點n的流量限制去掉就好了。
code
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> using namespace std; struct line{int to,next,c; }a[200001]; queue<int>f; int n,d[1001],s,e,num[1001],l,tot,ls[1001],ans; int ff[1001]; void addl(int x,int y,int z) {a[++tot].to=y;a[tot].next=ls[x];a[tot].c=z;ls[x]=tot;a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot; } bool bfs() {memset(d,0,sizeof(d));d[s]=1;f.push(s);while (!f.empty()){int x=f.front();for (int i=ls[x];i>=0;i=a[i].next){int y=a[i].to;if (a[i].c>0 && d[y]==0){d[y]=d[x]+1;f.push(y);}}f.pop();}if (d[e]) return true;else return false; } int dinic(int x,int flow) {int rest=0,k;if (x==e) return flow;for (int i=ls[x];i>=0;i=a[i].next){int y=a[i].to;if (a[i].c>0&&d[y]==d[x]+1&&flow>rest){rest+=(k=(dinic(y,min(flow-rest,a[i].c))));a[i].c-=k;a[i^1].c+=k;}}if (!rest) d[x]=0;return rest; } int main() {tot=-1;memset(ls,-1,sizeof(ls));scanf("%d",&n);s=0;e=2*n+1;for (int i=1;i<=n;i++)scanf("%d",&num[i]);for (int i=n;i>=1;i--){ff[i]=max(ff[i],1);for (int j=i+1;j<=n;j++)if (num[i]<=num[j]){ff[i]=max(ff[i],ff[j]+1);}l=max(l,ff[i]);}printf("%d\n",l);if (l==1){printf("%d\n%d",n,n);return 0;}for (int i=1;i<=n;i++){addl(2*i-1,2*i,1);if (ff[i]==l)addl(s,2*i-1,1);if (ff[i]==1)addl(2*i,e,1);}for (int i=1;i<n;i++)for (int j=i+1;j<=n;j++)if (num[i]<=num[j]&&ff[i]==ff[j]+1) addl(2*i,2*j-1,1);while (bfs()) ans+=dinic(s,1e9);printf("%d\n",ans);if (ff[1]==l)addl(1,2,1e9),addl(s,1,1e9);addl(2*n-1,2*n,1e9);addl(2*n,e,1e9);//ans=0;while (bfs()) ans+=dinic(s,1e9);printf("%d",ans); } 創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的P2766-最长不下降子序列问题【网络流,dp】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 丰田汽车:美国工厂部分工人明年起可获得近
- 下一篇: P1991-无线通讯网【最小生成树,瓶颈