zoukankan      html  css  js  c++  java
  • POJ3469 Dual Core CPU(最小割)

    题意:给你n个模块,每个模块在A核花费为ai,在B核跑花费为bi,然后由m个任务(ai,bi,wi),表示如果ai,bi不在同一个核上跑,额外的花费为wi,求最小的花费。

    一开始想的时候以为是费用流,但想着想着觉得,这么大的数据量绝对不可能是费用流。最后发现它是一个最小割模型。实际上就是要将网络里的模块划分成s-t两个点集,然后我们合适的构造一下边就可以使得对应的最小割就是我们的答案,构造的方法是这样的:当模块属于A集的时候,花费为ai,所以就从向t连一条ai的边,而当模块属于B集的时候,花费为bi,所以就由s连一条向bi的边。然后对于每个任务,当ai,bi不同的时候花费为mi,所以就由ai,bi连两条容量为wi的边,跑一下最大流就可以得出对应的最小花费了。代码将《挑战》上的模板化了一下,以后用起来会方便点吧~

    #pragma warning(disable:4996)
    #include<iostream>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<cstdio>
    #include<vector>
    #include<cmath>
    #include<queue>
    #define ll long long
    #define maxn 23500
    #define maxe 1000000
    #define inf 1100000000
    using namespace std;
    
    struct Edge
    {
    	int u, v, cap;
    	int nxt;
    }edge[maxe];
    
    int head[maxn];
    int n, m;
    
    struct Dicnic
    {
    	int level[maxn];
    	int iter[maxn];
    	int add;
    	void init(){
    		add = 0; memset(head, -1, sizeof(head)); 
    		memset(iter, -1, sizeof(iter));
    	}
    	void insert(int u, int v, int c){
    		edge[add].u = u; edge[add].v = v; edge[add].cap = c;
    		edge[add].nxt = head[u]; head[u] = add++;
    		edge[add].u = v; edge[add].v = u; edge[add].cap = 0;
    		edge[add].nxt = head[v]; head[v] = add++;
    	}
    	void bfs(int s){
    		memset(level, -1, sizeof(level));
    		queue<int> que;
    		level[s] = 0;
    		que.push(s);
    		while (!que.empty()){
    			int v = que.front(); que.pop();
    			for (int i = head[v]; i != -1; i = edge[i].nxt){
    				Edge &e = edge[i];
    				if (e.cap > 0 && level[e.v] < 0){
    					level[e.v] = level[v] + 1;
    					que.push(e.v);
    				}
    			}
    		}
    	}
    
    	int dfs(int v, int t, int f){
    		if (v == t) return f;
    		for (int &i = iter[v]; i != -1; i = edge[i].nxt){
    			Edge &e = edge[i]; Edge &reve = edge[i ^ 1];
    			if (e.cap > 0 && level[v] < level[e.v]){
    				int d = dfs(e.v, t, min(f, e.cap));
    				if (d>0){
    					e.cap -= d; reve.cap += d;
    					return d;
    				}
    			}
    		}
    		return 0;
    	}
    
    	int max_flow(int s, int t){
    		int flow = 0;
    		for (;;){
    			bfs(s);
    			if (level[t] < 0) return flow;
    			memcpy(iter, head, sizeof(iter));
    			int f;
    			while ((f = dfs(s, t, inf))>0){
    				flow += f;
    			}
    		}
    	}
    }net;
    
    int a[maxn], b[maxn];
    
    int main()
    {
    	while (cin >> n >> m){
    		net.init();
    		int s = 0, t = n + 1;
    		for (int i = 1; i <= n; i++) {
    			scanf("%d", a + i); scanf("%d", b + i);
    			net.insert(i, t, a[i]);
    			net.insert(s, i, b[i]);
    		}
    		int ui, vi, wi;
    		for (int i = 0; i < m; i++){
    			scanf("%d%d%d", &ui, &vi, &wi);
    			net.insert(ui, vi, wi);
    			net.insert(vi, ui, wi);
    		}
    		printf("%d
    ", net.max_flow(s,t));
    	}
    	return 0;
    }
    
  • 相关阅读:
    [转]Modernizr的介绍和使用
    java动态代理使用详解
    ajax上传文件以及使用中常见问题处理
    cmd下查询端口占用以及根据进程id名称结束进程
    水平居中 垂直居中
    inline-block和float
    一起入门前端(三)
    一起入门前端(二)
    一起入门前端(一)
    WPF初学——自定义样式
  • 原文地址:https://www.cnblogs.com/chanme/p/3650528.html
Copyright © 2011-2022 走看看