标签:click 集合 splay stack tar const org als 解题思路
在一个由核A和核B组成的双核CPU上执行N个任务,任务i在核A上执行,花费Ai,在核B上执行,花费为Bi,而某两个任务之间可能需要进数据交互,如果两个任务在同一个核上执行,那么数据交互将没有花费,如果在不同核上执行,将产生wi的花费,问将n个任务全部执行产生的最小花费 。
题目要求将n个任务分配为两个不同的集合,使得执行n个任务总花费最少,这类的题目我们一般将其转化为最小割问题,即花费最小的代价将n个点分为两部分。建图如下:
1)由源点向每个任务建一条容量为Ai的边
2)由每个任务向汇点建一条容量为Bi的边
3)对于不在同一核上运行的两个任务a,b,将产生额外的w花费,我们在a,b之间建两条容量为w的边,分为是a->b,b->a
最后我们在构建的图中跑最小割并输出最小割即可。
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<queue> #include<string> #include<fstream> #include<vector> #include<stack> #include <map> #include <iomanip> #define bug cout << "**********" << endl #define show(x, y) cout<<"["<<x<<","<<y<<"] " #define LOCAL = 1; using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; const ll mod = 1e9 + 7; const int Max = 4e6 + 10; struct Edge { int to, flow, next; } edge[Max << 1]; int n, m, s, t; int head[Max], tot; int dis[Max], cur[Max]; void init() { memset(head, -1, sizeof(head)); tot = 0; s = 0; t = n + 1; } void add(int u, int v, int flow) { edge[tot].to = v; edge[tot].flow = flow; edge[tot].next = head[u]; head[u] = tot++; } bool bfs() { memset(dis, -1, sizeof(dis)); queue<int> q; dis[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].flow > 0 && dis[v] == -1) { dis[v] = dis[u] + 1; if (v == t) return true; q.push(v); } } } return false; } int dfs(int u, int flow_in) { if (u == t) return flow_in; int flow_out = 0; for (int i = cur[u]; i != -1; i = edge[i].next) { cur[u] = i; int v = edge[i].to; if (dis[v] == dis[u] + 1 && edge[i].flow > 0) { int flow = dfs(v, min(flow_in, edge[i].flow)); if (flow == 0) continue; flow_in -= flow; flow_out += flow; edge[i].flow -= flow; edge[i ^ 1].flow += flow; if (flow_in == 0) break; } } return flow_out; } int Dinic(int ans) { int sum = 0; while (bfs()) { for (int i = 0; i <= ans; i++) cur[i] = head[i]; sum += dfs(s, inf); } return sum; } int main() { #ifdef LOCAL //freopen("input.txt", "r", stdin); //freopen("output.txt", "w", stdout); #endif while (scanf("%d%d", &n, &m) != EOF) { init(); for (int i = 1, a, b; i <= n; i++) { scanf("%d%d", &a, &b); add(s, i, a); add(i, s, 0); add(i, t, b); add(t, i, 0); } for(int i =1, u, v, flow; i <= m ;i ++) { scanf("%d%d%d",&u,&v,&flow); add(u,v,flow); add(v,u,flow); } printf("%d\n",Dinic(n+1)); } return 0; }
POJ - 3469 Dual Core CPU (最小割)
标签:click 集合 splay stack tar const org als 解题思路
原文地址:https://www.cnblogs.com/winter-bamboo/p/11391925.html