题目链接:Dual Core CPU
解题思路:这里有N个模式,运行在2个CPU上,每一个模式在每一个CPU上面运行的花费不同,而且部分模式间必须通信,如果都运行在一个CPU上面就不需要额外的耗费,否则需要额外的耗费W。求最小耗费的方法。
(1)—CPU1看做源点,CPU2看做汇点,将每一个模式连接源汇点,容量为题目给的花费。这样的话这个CPU的耗费只能是两个耗费中的最小着,应为不能超出容量。
(2)—再将需要通信的模式之间连接一条无向边,容量都为花费。如果这里的无向边没有流通过的话,说明他们在同一个CPU上面,如果有流通过但是没有满的话,说明选择了一个CPU中较大花费的模式,多余的流从这里走过,但是这样还是比在不同的CPU的花费小,如果正好满流量说明在不同的CPU之间。
(3)—说了这么多大家还是可以画一个图看看,比较直观,还有就是说这个是求最小割,其实最小割等于最大流。
#include<stdio.h> #include<string.h> #include<queue> #define MAXV 300100 #define MAXE 600100 #define INF 0x3f3f3f3f using namespace std; struct Edge{ int v, f, nxt; }; int n, src, sink; int g[MAXV]; int nume; Edge e[MAXE]; void addedge(int u, int v, int c, int h){ e[++nume].v = v; e[nume].f = c; e[nume].nxt = g[u]; g[u] = nume; e[++nume].v = u; e[nume].f = h; e[nume].nxt = g[v]; g[v] = nume; } void init(){ memset(g, 0, sizeof(g)); memset(e, 0, sizeof(e)); nume = 1; } queue<int> que; bool vis[MAXV]; int dist[MAXV]; void bfs(){ memset(dist, 0, sizeof(dist)); while(!que.empty()) que.pop(); vis[src] = true; que.push(src); while(!que.empty()){ int u = que.front(); que.pop(); for(int i = g[u]; i; i = e[i].nxt){ if(e[i].f && !vis[e[i].v]){ que.push(e[i].v); dist[e[i].v] = dist[u] + 1; vis[e[i].v] = true; } } } } int dfs(int u, int delta){ if(u == sink){ return delta; } else{ int ret = 0; for(int i = g[u]; delta && i; i = e[i].nxt){ if(e[i].f && dist[e[i].v] == dist[u] + 1){ int dd = dfs(e[i].v, min(e[i].f, delta)); e[i].f -= dd; e[i ^ 1].f += dd; delta -= dd; ret += dd; } } return ret; } } int maxflow(){ int ret = 0; while(true){ memset(vis, 0, sizeof(vis)); bfs(); if(!vis[sink]) return ret; ret += dfs(src, INF); } } //以上均为DINIC的模板 int main(){ int i, j, k; int n, m; int a, b, c; while(scanf("%d%d", &n, &m) != EOF){ init(); src = 0; sink = n + 1; for(i = 1; i <= n; i++){ scanf("%d%d", &a, &b); addedge(src, i, a, 0); addedge(i, sink, b, 0); } for(i = 0; i < m; i++){ scanf("%d%d%d", &a, &b, &c); addedge(a, b, c, c); } printf("%d\n", maxflow()); } return 0; }