P2766 [网络流24题]最长不下降子序列问题

ha~

«问题描述:

给定正整数序列$x_1,...,x_n$ 。$n<=500$

求(1)计算其最长不下降子序列的长度$s$。

(2)计算从给定的序列中最多可取出多少个长度为$s$的不下降子序列。

(3)如果允许在取出的序列中多次使用$x_1$和$x_n$,则从给定序列中最多可取出多少个长度为$s$的不下降子序列。


(1)暴力n方解决

(2)建分层图,把图每个顶点i按照F[i]的不同分为若干层,这样图中从S出发到T的任何一条路径都是一个满足条件的最长不下降子序列。由 S 向所有$ f_i = 1$ 的$ i $连容量为$ 1 $的边,由 所有$ f_i = s $的$ i $向$ T $连容量为$ 1$ 的边。对于所有的$ (i,j)$,若$ i < j,fi +1 = fj$,则由$ i$ 向$ j$ 连容量为 $1$ 的边。这样一来,所 有从 $S$ 出发到达$ T$ 的的路径都是一个长度为 $s $的上升子序 列。

注意拆点,以保证同一个数不会重复使用。一个连入边,一个连出边,两个点 之间连流量为 1 的限制边。

注意事项: line49的条件判断注意$f[j]+i==f[i]$的前提是要$a[j]<=a[i]$才可以连边!

(3)把之前的边的流量限制改一下即可,对1号和n号微调后原样跑。

注意事项(其实网上绝大部分题解好像都忽略了):建边时s向1号点的容量不可为无穷,应设为n,  n号点连t同理.

比如这个毒瘤数据

1

1

绝大部分题解输的是INF,但其实是1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<int,int> pii;
 5 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;}
 6 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;}
 7 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
 8 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
 9 template<typename T>inline T read(T&x){
10     x=0;char c;while(!isdigit(c=getchar()))if(isalpha(c))return x=(int)c;
11     while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();return x;
12 }
13 const int N=500+7,M=150000+7,INF=0x3f3f3f3f;
14 int w[2][M<<1],v[2][M<<1],Next[2][M<<1],Head[2][N<<1],cur[2][N<<1],dis[2][N<<1],tot[2],s,t,n;
15 inline void Addedge(int x,int y,int z,int p){
16     v[p][++tot[p]]=y,Next[p][tot[p]]=Head[p][x],Head[p][x]=tot[p],w[p][tot[p]]=z;
17     v[p][++tot[p]]=x,Next[p][tot[p]]=Head[p][y],Head[p][y]=tot[p],w[p][tot[p]]=0;
18 }
19 #define y v[p][j]
20 inline char bfs(int p){
21     queue<int> q;q.push(s),memset(dis[p],0,sizeof dis[p]),dis[p][s]=1;
22     for(register int i=1;i<=(n<<1)+2;++i)cur[p][i]=Head[p][i];
23     while(!q.empty()){
24         int x=q.front();q.pop();
25         for(register int j=Head[p][x];j;j=Next[p][j])if(w[p][j]&&!dis[p][y]){
26             dis[p][y]=dis[p][x]+1,q.push(y);
27             if(y==t)return 1;
28         }
29     }
30     return 0;
31 }
32 int dinic(int x,int flow,int p){
33     if(!flow||x==t)return flow;
34     int rest=flow,k;
35     for(register int j=cur[p][x];j&&rest;cur[p][x]=j,j=Next[p][j])if(w[p][j]&&dis[p][y]==dis[p][x]+1){
36         if(!(k=dinic(y,_min(rest,w[p][j]),p)))dis[p][y]=0;
37         rest-=k,w[p][j]-=k,w[p][j^1]+=k;
38     }
39     return flow-rest;
40 }
41 #undef y
42 int a[N],f[N],ans,maxflow;
43 
44 int main(){//freopen("P2766.in","r",stdin);//freopen("P2766.txt","w",stdout);
45     read(n);s=(n<<1)+1,t=s+1,tot[0]=tot[1]=1;
46     for(register int i=1;i<=n;++i){
47         read(a[i]);f[i]=1;
48         for(register int j=1;j<i;++j)if(a[j]<=a[i])MAX(f[i],f[j]+1);
49         for(register int j=1;j<i;++j)if(f[j]+1==f[i]&&a[j]<=a[i])Addedge(j+n,i,1,0),Addedge(j+n,i,1,1);
50         MAX(ans,f[i]),Addedge(i,i+n,1,0);if(f[i]==1)Addedge(s,i,1,0),i==1?Addedge(s,i,n,1):Addedge(s,i,1,1);
51         if(i==1||i==n)Addedge(i,i+n,n,1);else Addedge(i,i+n,1,1);
52     }
53     printf("%d\n",ans);
54     for(register int i=1;i<=n;++i)if(f[i]==ans)Addedge(i+n,t,1,0),i==n?Addedge(i+n,t,n,1):Addedge(i+n,t,1,1);
55     while(bfs(0))maxflow+=dinic(s,n,0);
56     printf("%d\n",maxflow);maxflow=0;
57     while(bfs(1))maxflow+=dinic(s,n,1);
58     printf("%d\n",maxflow);
59     return 0;
60 }

猜你喜欢

转载自www.cnblogs.com/saigyouji-yuyuko/p/10357439.html
今日推荐