zoukankan      html  css  js  c++  java
  • 洛谷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;
    }
    

      

  • 相关阅读:
    WPF XAML之bing使用StringFormat
    C#程序以管理员权限运行
    注册表REG文件编写大全
    linux 的基本操作(编写shell 脚本)
    linux的基本操作(正则表达式)
    linux的基本操作(shell 脚本的基础知识)
    linux的基本操作(RPM包或者安装源码包)
    linux的基本操作(文件压缩与打包)
    linux的基本操作(文本编辑工具vim)
    linux的基本操作(磁盘管理)
  • 原文地址:https://www.cnblogs.com/guangheli/p/10365900.html
Copyright © 2011-2022 走看看