洛谷P2766 最长不下降子序列问题 网络流_DP
Code:
#include<cstdio> #include<iostream> #include<vector> #include<algorithm> #include<queue> #include<cstring> using namespace std; const int INF=1000000; const int maxn=600; # define pb push_back int A[maxn],f[maxn]; int s,t; int ans=0; struct Edge{ int from,to,cap; Edge(int u,int v,int c):from(u),to(v),cap(c) {} }; struct Dicnic{ vector<Edge>edges; vector<int>G[maxn]; int d[maxn],vis[maxn],cur[maxn]; queue<int>Q; void addedge(int u,int v,int c){ edges.pb(Edge(u,v,c)); //正向弧 edges.pb(Edge(v,u,0)); //反向弧 int m=edges.size(); G[u].pb(m-2); G[v].pb(m-1); } int BFS() { memset(vis,0,sizeof(vis)); d[s]=0,vis[s]=1;Q.push(s); while(!Q.empty()){ int u=Q.front();Q.pop(); int sz=G[u].size(); for(int i=0;i<sz;++i){ Edge e=edges[G[u][i]]; if(!vis[e.to]&&e.cap>0){ d[e.to]=d[u]+1,vis[e.to]=1; Q.push(e.to); } } } return vis[t]; } int dfs(int x,int a){ if(x==t)return a; int sz=G[x].size(); int f,flow=0; for(int i=cur[x];i<sz;++i){ Edge e=edges[G[x][i]]; cur[x]=i; if(d[e.to]==d[x]+1&&e.cap>0){ f=dfs(e.to,min(a,e.cap)); if(f) { int u=G[x][i]; a-=f; edges[u].cap-=f; edges[u^1].cap+=f; flow+=f; if(a==0)break; } } } return flow; } int maxflow(){ while(BFS()){ memset(cur,0,sizeof(cur)); ans+=dfs(s,INF); } return ans; } }op; int main() { int n;cin>>n; for(int i=1;i<=n;++i)cin>>A[i]; f[1]=1; int anss=1; for(int i=2;i<=n;++i){ f[i]=1; for(int j=1;j<i;++j) if(A[j]<=A[i]){f[i]=max(f[i],f[j]+1);anss=max(anss,f[i]);} } s=0,t=510; for(int i=1;i<=n;++i){ if(f[i]==1)op.addedge(s,i,1); if(f[i]==anss)op.addedge(i,t,1); } for(int i=1;i<n;++i) for(int j=i+1;j<=n;++j)if(f[j]==f[i]+1&&A[j]>=A[i])op.addedge(i,j,1); cout<<anss<<endl; cout<<op.maxflow()<<endl; if(anss==1){cout<<n<<endl;return 0;} if(f[1]==anss)op.addedge(1,t,INF); if(f[n]==anss)op.addedge(n,t,INF); //出边 op.addedge(s,1,INF); if(f[n]==1)op.addedge(s,n,INF); //入边 for(int i=2;i<=n;++i) { if(A[i]>=A[1]&&f[i]==f[1]+1)op.addedge(1,i,INF); } int fin=op.maxflow(); if(fin>=INF) { int t=fin/INF; fin=(fin+t)%INF; } cout<<fin; return 0; }