一道最小割典型题。
对于一个模块x,我们把他拆成两个点x1, x2:从源点向x1连一条ai的边,割掉他代表x在A机器上的花费;同理x2向汇点连一条bi的边,割掉他代表在B机器上的花费。因为每一个模块必须完成,所以x1和x2连一条INF的边,割掉他的代价是无穷的。
题中还说如果x和y不在同一机器完成的话,会付出额外的代价。所以我们把x1和y1,x2和y2连一条边权为这个代价的边。
然后跑最大流求最小割即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 4e4 + 5; 21 const int maxe = 1e7 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, m, t; 39 40 struct Edge 41 { 42 int nxt, from, to, cap, flow; 43 }e[maxe]; 44 int head[maxn], ecnt = 1; 45 void addEdge(int x, int y, int w) 46 { 47 e[++ecnt] = (Edge){head[x], x, y, w, 0}; 48 head[x] = ecnt; 49 e[++ecnt] = (Edge){head[y], y, x, 0, 0}; 50 head[y] = ecnt; 51 } 52 53 int dis[maxn]; 54 bool bfs() 55 { 56 Mem(dis, 0); dis[0] = 1; 57 queue<int> q; q.push(0); 58 while(!q.empty()) 59 { 60 int now = q.front(); q.pop(); 61 for(int i = head[now]; i; i = e[i].nxt) 62 { 63 if(!dis[e[i].to] && e[i].cap > e[i].flow) 64 { 65 dis[e[i].to] = dis[now] + 1; 66 q.push(e[i].to); 67 } 68 } 69 } 70 return dis[t]; 71 } 72 int cur[maxn]; 73 int dfs(int now, int res) 74 { 75 if(now == t || res == 0) return res; 76 int flow = 0, f; 77 if(!cur[now]) cur[now] = head[now]; 78 for(int &i = cur[now]; i; i = e[i].nxt) 79 { 80 if(dis[e[i].to] == dis[now] + 1 && (f = dfs(e[i].to, min(res, e[i].cap - e[i].flow))) > 0) 81 { 82 e[i].flow += f; e[i ^ 1].flow -= f; 83 flow += f; res -= f; 84 if(res == 0) break; 85 } 86 } 87 return flow; 88 } 89 90 int minCut() 91 { 92 int flow = 0; 93 while(bfs()) 94 { 95 Mem(cur, 0); 96 flow += dfs(0, INF); 97 } 98 return flow; 99 } 100 101 int main() 102 { 103 n = read(); m = read(); t = n + n + 1; 104 for(int i = 1; i <= n; ++i) 105 { 106 int x = read(), y = read(); 107 addEdge(0, i, x); addEdge(i + n, t, y); 108 addEdge(i, i + n, INF); 109 } 110 for(int i = 1; i <= m; ++i) 111 { 112 int x = read(), y = read(), w = read(); 113 addEdge(x, y, w); addEdge(y, x, w); 114 addEdge(x + n, y + n, w); addEdge(y + n, x + n, w); 115 } 116 write(minCut()), enter; 117 return 0; 118 }