一.原题链接:http://poj.org/problem?id=3469
二.题目大意:在双核CPU中,每个任务只能在其中一个核运行,而且所有任务必须同时运行,给出它们分别在2个核里面的花费,如果某些任务不在同一个核运行,那么给出它们的花费。求它们全部运行时的最小花费。
三.解题思路:全部任务要同时运行,而且每个任务在2个不同的核里面的花费是不同的。我们可以想到建立一个源点和一个汇点,容量为其花费,而不在同一个核运行的任务建双向边,这样如果能够把源点和汇点分开的割表示的就是其花费,s能到达的点在t上处理,其余点在t上处理。而最小花费就是最小割,由最小割最大流定理,我们就愉快地转化为求最大流。
四.坑点:
1.数据量太大,无法用邻接矩阵,只能用邻接表。
2.i^1表示如果i为偶数就加1,i是奇数就减1,由于我代码的cnt是从0开始的,建边的时候建的残余网络那条反向边和正向边是连续的,因此这样就可以在O(1)访问到反向弧了。
3.边的最大值要很大,绝对不止200000,刚开始一直RE。
五.代码
1.Dinic 15148K 7094MS
#include <iostream> #include <cstdio> #include <queue> #include <cstring> #include <cstdlib> using namespace std; const int INF = 0x3f3f3f3f, MAX_N = 30000, MAX_M = 1000000; struct Edge { int v, w, next; }; int N, M, cnt, head[MAX_M], dist[MAX_N], s, t; Edge edges[MAX_M]; void init() { cnt = 0; s = N + 1, t = N + 2; memset(head, -1, sizeof(head)); } void addEdge(int u, int v, int weight) { edges[cnt] = (Edge){v, weight, head[u]}; head[u] = cnt++; edges[cnt] = (Edge){u, 0, head[v]}; head[v] = cnt++; } bool BFS() { int i, cur; queue <int> que; que.push(s); memset(dist, -1, sizeof(dist)); dist[s] = 0; while(!que.empty()){ cur = que.front(); que.pop(); for(i = head[cur]; i != -1; i = edges[i].next) if(-1 == dist[edges[i].v] && edges[i].w){ dist[edges[i].v] = dist[cur] + 1; que.push(edges[i].v); } } return dist[t] != -1; } int DFS(int start, int curFlow) { if(start == t) return curFlow; int i, j, minFlow = 0, v, temp; for(i = head[start]; i != -1; i = edges[i].next){ v = edges[i].v; if(dist[start] == dist[v] - 1 && edges[i].w > 0){ temp = DFS(v, min(edges[i].w, curFlow)); edges[i].w -= temp; edges[i^1].w += temp; curFlow -= temp; minFlow += temp; if(0 == curFlow) break; } } return minFlow; } int Dinic() { int res = 0; while(BFS()){ res += DFS(s, INF); } return res; } int main() { //freopen("in.txt", "r", stdin); int i, j, cost1, cost2, u, v; scanf("%d%d", &N, &M); init(); for(i = 1; i <= N; i++){ scanf("%d%d", &cost1, &cost2); addEdge(s, i, cost1); addEdge(i, t, cost2); } for(i = 1; i <= M; i++){ scanf("%d%d%d", &u, &v, &cost1); addEdge(u, v, cost1); addEdge(v, u, cost1); } printf("%d\n", Dinic()); return 0; }