[POJ3469]Dual Core CPU(最小割)

题目链接:http://poj.org/problem?id=3469

题意:CPU两核拿来跑n个任务,每个任务在每个核上有花费,而且会有m对任务有交互,假如不在同一个核运行则需w的花费。问最小花费。

这题的意思就是把n个任务分成两部分,使得花费最小,《挑战》书上称此类问题可以通过巧妙的建图转化为最小割问题。

对于两个集合而言,总花费是守恒的,不妨设两个集合花费分别是A,a,B,b。AB分别是单独的花费,ab分别是存在交互的花费。

A和B分别看作与源点和汇点同侧的点集,相当于求一个割,将点分成两部分,希望割最小,就是求最大流了。

常规建图就行,假如两个点存在交互,但是在同一个集合里,也不会属于割的一部分。

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <iomanip>
  4 #include <cstring>
  5 #include <climits>
  6 #include <complex>
  7 #include <cassert>
  8 #include <cstdio>
  9 #include <bitset>
 10 #include <vector>
 11 #include <deque>
 12 #include <queue>
 13 #include <stack>
 14 #include <ctime>
 15 #include <set>
 16 #include <map>
 17 #include <cmath>
 18 using namespace std;
 19 
 20 typedef struct Edge {
 21     int u, v, w, next;
 22 }Edge;
 23 
 24 const int inf = 0x7f7f7f7f;
 25 const int maxn = 20200;
 26 const int maxm = 200200;
 27 int cnt, dhead[maxn];
 28 int cur[maxn], dd[maxn];
 29 Edge dedge[maxm<<3];
 30 int S, T, N;
 31 
 32 void init() {
 33     memset(dhead, -1, sizeof(dhead));
 34     for(int i = 0; i < maxn; i++) dedge[i].next = -1;
 35     S = 0; cnt = 0;
 36 }
 37 
 38 void adde(int u, int v, int w, int c1=0) {
 39     dedge[cnt].u = u; dedge[cnt].v = v; dedge[cnt].w = w; 
 40     dedge[cnt].next = dhead[u]; dhead[u] = cnt++;
 41     dedge[cnt].u = v; dedge[cnt].v = u; dedge[cnt].w = c1; 
 42     dedge[cnt].next = dhead[v]; dhead[v] = cnt++;
 43 }
 44 
 45 bool bfs(int s, int t, int n) {
 46     queue<int> q;
 47     for(int i = 0; i < n; i++) dd[i] = inf;
 48     dd[s] = 0;
 49     q.push(s);
 50     while(!q.empty()) {
 51         int u = q.front(); q.pop();
 52         for(int i = dhead[u]; ~i; i = dedge[i].next) {
 53             if(dd[dedge[i].v] > dd[u] + 1 && dedge[i].w > 0) {
 54                 dd[dedge[i].v] = dd[u] + 1;
 55                 if(dedge[i].v == t) return 1;
 56                 q.push(dedge[i].v);
 57             }
 58         }
 59     }
 60     return 0;
 61 }
 62 
 63 int dinic(int s, int t, int n) {
 64     int st[maxn], top;
 65     int u;
 66     int flow = 0;
 67     while(bfs(s, t, n)) {
 68         for(int i = 0; i < n; i++) cur[i] = dhead[i];
 69         u = s; top = 0;
 70         while(cur[s] != -1) {
 71             if(u == t) {
 72                 int tp = inf;
 73                 for(int i = top - 1; i >= 0; i--) {
 74                     tp = min(tp, dedge[st[i]].w);
 75                 }
 76                 flow += tp;
 77                 for(int i = top - 1; i >= 0; i--) {
 78                     dedge[st[i]].w -= tp;
 79                     dedge[st[i] ^ 1].w += tp;
 80                     if(dedge[st[i]].w == 0) top = i;
 81                 }
 82                 u = dedge[st[top]].u;
 83             }
 84             else if(cur[u] != -1 && dedge[cur[u]].w > 0 && dd[u] + 1 == dd[dedge[cur[u]].v]) {
 85                 st[top++] = cur[u];
 86                 u = dedge[cur[u]].v;
 87             }
 88             else {
 89                 while(u != s && cur[u] == -1) {
 90                     u = dedge[st[--top]].u;
 91                 }
 92                 cur[u] = dedge[cur[u]].next;
 93             }
 94         }
 95     }
 96     return flow;
 97 }
 98 
 99 int n, m;
100 int a, b, w;
101 
102 int main() {
103     // freopen("in", "r", stdin);
104     while(~scanf("%d%d",&n,&m)) {
105         init();
106         S = 0, T = n + 1, N = T + 1;
107         for(int i = 0; i < n; i++) {
108             scanf("%d%d",&a,&b);
109             adde(S, i+1, a);
110             adde(i+1, T, b);
111         }
112         for(int i = 0; i < m; i++) {
113             scanf("%d%d%d",&a,&b,&w);
114             adde(a, b, w);
115             adde(b, a, w);
116         }
117         printf("%d
", dinic(S,T,N));
118     }
119     return 0;
120 }
原文地址:https://www.cnblogs.com/kirai/p/6785487.html