• 最长递增子序列问题(费用流)


    http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=487

    费用流,每次沿着最长边增广

    //http://www.cnblogs.com/IMGavin/
    #include <iostream>
    #include <stdio.h>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <bitset>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    #define gets(A) fgets(A, 1e8, stdin)
    const int INF = 0x3F3F3F3F, N = 20008, MOD = 1003, M = 2000000;
    
    int len;
    int dp[N];//dp[i]表示当前状态若最长子序列长度为i+1时,序列最后位置数字(尽可能小)
    int LIS(int *a,int n){//n为a的长度,a为待处理序列,返回a最长子序列长度
        int i,j,len,pos;
        dp[0]=a[0];
        len=0;
        for(i=1;i<n;i++){
            pos=lower_bound(dp,dp+len+1,a[i])-dp;
            dp[pos]=a[i];
            if(pos>len){
                len++;
            }
        }
        len++;
        return len;
    }
    struct Node{
    	int u, v, cap, cost;
    	int next;
    }edge[M];//有向图,u到v的容量,费用
    int tot;
    int head[N], pre[N], path[N], dis[N];
    bool inq[N];
    
    void init(){
    	tot = 0;
    	memset(head, -1, sizeof(head));
    }
    
    void add(int u, int v, int cap, int cost){
    	edge[tot].u = u;
    	edge[tot].v = v;
    	edge[tot].cap = cap;
    	edge[tot].cost = cost;
    	edge[tot].next = head[u];
    	head[u] = tot++;
    	edge[tot].u = v;
    	edge[tot].v = u;
    	edge[tot].cap = 0;
    	edge[tot].cost = -cost;
    	edge[tot].next = head[v];
    	head[v] = tot++;
    }
    
    bool SPFA(int st, int des){//计算最小费用
    	memset(inq, 0, sizeof(inq));
    	memset(dis, 0x3f, sizeof(dis));
    	queue <int> q;
    	q.push(st);
    	dis[st] = 0;
    	inq[st] = true;
    	while(!q.empty()){
    		int u = q.front();
    		q.pop();
    		inq[u] = false;
    		for(int i = head[u]; ~i; i = edge[i].next){
    			int v = edge[i].v;
    			if(edge[i].cap > 0 && dis[v] > dis[u] + edge[i].cost){
    				dis[v] = dis[u] + edge[i].cost;
    				pre[v] = u;
    				path[v] = i;
    				if(!inq[v]){
    					inq[v] = true;
    					q.push(v);
    				}
    			}
    		}
    	}
    	return dis[des] == 1 - len;
    }
    
    int EdmondsKarp(int st, int des){//最小费用最大流
    	int mincost = 0, flow = 0;//最小费用与流量
    	while(SPFA(st, des)){
    		int f = INF;
    		for(int i = des; i != st; i = pre[i]){
                if(f > edge[path[i]].cap){
                    f = edge[path[i]].cap;
                }
    		}
    		for(int i = des; i != st; i = pre[i]){
    			edge[path[i]].cap -= f;
    			edge[path[i]^1].cap += f;
    		}
    		mincost += f * dis[des];
    		flow += f;
    	}
    	return flow;
    }
    
    int a[N];
    int in[N], out[N];
    int main(){
    	int n;
    	while(~scanf("%d", &n)){
    		memset(in, 0, sizeof(in));
    		memset(out, 0, sizeof(out));
    		for(int i = 1; i <= n; i++){
    			scanf("%d", &a[i]);
    		}
    		len = LIS(a + 1, n);
    		printf("%d
    ", len);
    		init();
    		for(int i = 1;  i < n; i++){
    			for(int j = i + 1; j <= n; j++){
    				if(a[i] < a[j]){
    					add(i, j, 1, -1);
    					out[i]++;
    					in[j]++;
    				}
    			}
    		}
    		for(int i = 1; i <= n; i++){
    			if(!in[i]){
    				add(0, i, 1, 0);
    			}
    			if(!out[i]){
    				add(i, n + 1, 1, 0);
    			}
    		}
    		int ans = EdmondsKarp(0, n + 1);
    		printf("%d
    ", ans);
    		add(0, 1, INF, 0);
    		add(n, n + 1, INF, 0);
    		ans += EdmondsKarp(0, n + 1);
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    linux中的 tar命令的 -C 参数,以及其它一些参数
    dockerfile 介绍
    linux安装mysql后root无法登录
    centos搭建本地yum源,
    centos7下载自定义仓库的镜像设置方法
    QT TCP文件上传服务器
    QT UDP聊天小程序
    QT 网络编程三(TCP版)
    QT 网络编程二(UDP版本)
    QT 网络编程一
  • 原文地址:https://www.cnblogs.com/IMGavin/p/6371343.html
Copyright © 2020-2023  润新知