zoukankan      html  css  js  c++  java
  • 数字梯形问题(费用流)

    费用流,拆点

    //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 = 1008, MOD = 1003, M = 2000000;
    
    const double EPS = 1e-6;
    
    int val[N][N];
    
    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];
    int m, n;
    
    void init(){
    	tot = 0;
    	memset(head, -1, sizeof(head));
    }
    
    void add(int u, int v, int cost, int cap){
    	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] < INF;
    }
    
    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 mincost;
    }
    
    int cal1(){
    	init();
    	int tot = n * m + n * (n -1) / 2;
    	int st = 0, des = tot * 2 + 1;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			add(u, u + tot, -val[i][j], 1);
    		}
    	}
    		
    	for(int i = 0; i < n - 1; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			int v = (i + 1) * m + i * (i + 1) / 2 + j + 1;
    			add(u + tot, v, 0, 1);
    			add(u + tot, v + 1, 0, 1);
    		}
    	}
    	for(int i = 1; i <= m; i++){
    		add(st, i, 0, 1);
    	}
    	for(int i = 0; i < n + m - 1; i++){
    		int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1;
    		add(u + tot, des, 0, 1);
    	}
    	return -EdmondsKarp(st, des);
    }
    
    int cal2(){
    	init();
    	int tot = n * m + n * (n -1) / 2;
    	int st = 0, des = tot * 2 + 1;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			add(u, u + tot, -val[i][j], INF);
    		}
    	}
    		
    	for(int i = 0; i < n - 1; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			int v = (i + 1) * m + i * (i + 1) / 2 + j + 1;
    			add(u + tot, v, 0, 1);
    			add(u + tot, v + 1, 0, 1);
    		}
    	}
    	for(int i = 1; i <= m; i++){
    		add(st, i, 0, 1);
    	}
    	for(int i = 0; i < n + m - 1; i++){
    		int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1;
    		add(u + tot, des, 0, INF);
    	}
    	return -EdmondsKarp(st, des);
    }
    
    int cal3(){
    	init();
    	int tot = n * m + n * (n -1) / 2;
    	int st = 0, des = tot * 2 + 1;
    	for(int i = 0; i < n; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			add(u, u + tot, -val[i][j], INF);
    		}
    	}
    		
    	for(int i = 0; i < n - 1; i++){
    		for(int j = 0; j < m + i; j++){
    			int u = i * m + i * (i - 1) / 2 + j + 1;
    			int v = (i + 1) * m + i * (i + 1) / 2 + j + 1;
    			add(u + tot, v, 0, INF);
    			add(u + tot, v + 1, 0, INF);
    		}
    	}
    	for(int i = 1; i <= m; i++){
    		add(st, i, 0, 1);
    	}
    	for(int i = 0; i < n + m - 1; i++){
    		int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1;
    		add(u + tot, des, 0, INF);
    	}
    	return -EdmondsKarp(st, des);
    }
    
    int main(){
    	while(cin >> m >> n){		
    		for(int i = 0; i < n; i++){
    			for(int j = 0; j < m + i; j++){
    				scanf("%d", &val[i][j]);
    			}
    		}
    		cout<<cal1()<<endl;
    		cout<<cal2()<<endl;
    		cout<<cal3()<<endl;
    	}
    
    	return 0;
    }
    

      

  • 相关阅读:
    47 在 Java 程序中怎么保证多线程的运行安全?
    46 线程池中 submit() 和 execute() 方法有什么区别?
    前端能力和后端能力
    在HTML中限制input 输入框只能输入纯数字
    footer固定在页面底部的实现方法总结
    在网站建设的时候需要考虑哪些因素?
    CENTOS中cat命令中文乱码 VIM乱码设置
    腾讯实验室LAMP搭建DZ
    运算符总结
    Typora专业写手都在用
  • 原文地址:https://www.cnblogs.com/IMGavin/p/6388077.html
Copyright © 2011-2022 走看看