POJ 3469 解题报告

来源:互联网 发布:html5与webgl编程 pdf 编辑:程序博客网 时间:2024/06/06 20:41

这道题大家的做法都是最小割,构图也一样:对每个点,从source加一条capacity为Ai的边,再加一条从该边到sink的capacity为Bi的边。对需要data exchange的点,增加一条capacity为m的双向边。至于为什么这样构图,discuss里面有些说明。当然,我也不是特别清楚原理。

由于最小割就是最大流,所以就转化为考验最大流标程效率的问题。我之前的Edmonds-Karp算法在这里TLE了。遂不得不改变标程为dinic。因为dinic看起来很简单。dinic的理解确实简单些,可以看做EK的优化。

最好的dinic解释可以见这里:http://comzyh.com/blog/archives/568/

dinic本身也有很多优化,多路增广是其中之一:http://poj.org/showmessage?message_id=129060。

别的优化如当前边优化,我自己没能理解其必要性,也没有应用。感兴趣的话,这两个链接有很好的实现:

http://www.cnblogs.com/zhsl/archive/2012/12/03/2800092.html

http://www.cs.cmu.edu/~15451/lectures/lec11/dinic.pdf

thestoryofsnow3469Accepted6016K3782MSC++5140B

/* ID: thestor1 LANG: C++ TASK: poj3469 */#include <iostream>#include <fstream>#include <cmath>#include <cstdio>#include <cstring>#include <limits>#include <string>#include <vector>#include <list>#include <set>#include <map>#include <queue>#include <stack>#include <algorithm>#include <cassert>using namespace std;const int MAXN = 20000 + 2;const int MAXM = 200000;class Edge{public:// edge (`u` -> `v`) with capacity `w`int v, w;// use (pre-allocated) array as linked list here// thus we need `next` point to next edge in adjacent list of node `u`int next;// the reverse edge (from `v` -> `u`) should be (edgeno ^ 1)// as we are adding edges sequentially// for convenience in updating residual graph Edge(){this->v = -1;this->w = -1;this->next = -1;}};// construct level graph(GL) using BFS// return true if sink is reachable from source (thus there is GL)// return false otherwisebool BFS(int GL[], int Queue[], int adjs[], Edge edges[], const int N, const int source, const int sink){// initialize all levels as negative(-1)memset(GL, -1, N * sizeof(int));GL[source] = 0;int front = 0, rear = 0;Queue[0] = source;while (front <= rear){int u = Queue[front];front++;int e = adjs[u];while (e >= 0){int v = edges[e].v;// not set before (GL in this case can be thought as visited[])if (GL[v] < 0 && edges[e].w > 0){GL[v] = GL[u] + 1;rear++;assert (rear < N);Queue[rear] = v;}// set as next node in adjacent liste = edges[e].next;}}if (GL[sink] > 0){return true;}else{return false;}}int DFS(int u, int low, int GL[], int adjs[], Edge edges[], const int sink){// if reached sink, then return the narrowest capacity in the path (low)if (u == sink || !low){return low;}// otherwise recursively check each adjacent edge (thus reach next node)int total = 0;int e = adjs[u];while (e >= 0 && low){int v = edges[e].v;// v is at next level in level graphif (GL[v] == GL[u] + 1 && edges[e].w > 0){int flow = DFS(v, min(low, edges[e].w), GL, adjs, edges, sink);// if can reach sink (because otherwise `flow` will be 0)if (flow > 0){// update residual graphedges[e].w -= flow;edges[e ^ 1].w += flow;low -= flow;total += flow;}}e = edges[e].next;}// optimization, no need to try this node any more if it has no outgoing flowsif (total == 0){GL[u] = -1;}return total;}// for more about dinic: http://comzyh.com/blog/archives/568/int dinic(int GL[], int Queue[], int adjs[], Edge edges[], const int N, const int source, const int sink){int maxflow = 0;// construct level graph G_L using BFS// until sink cannot be reached from sourcewhile (BFS(GL, Queue, adjs, edges, N, source, sink)){// search a blocking flow (augment path) using DFS// int flow = DFS(source, numeric_limits<int>::max(), GL, adjs, edges, sink);// while (flow > 0)// {// maxflow += flow;// flow = DFS(source, numeric_limits<int>::max(), GL, adjs, edges, sink);// }maxflow += DFS(source, numeric_limits<int>::max(), GL, adjs, edges, sink);}return maxflow;}int main(){Edge edges[2 * MAXN + 2 * MAXM + 2 * MAXN];int edgeno = 0;int adjs[MAXN];// int current[MAXN];int GL[MAXN];int Queue[MAXN];int N, M;scanf("%d%d", &N, &M);memset(adjs, -1, (N + 2) * sizeof(int));for (int i = 0; i < N; ++i){int Ai, Bi;scanf("%d%d", &Ai, &Bi);// 0 -> i + 1, capacity: Aiedges[edgeno].v = i + 1;edges[edgeno].w = Ai;edges[edgeno].next = adjs[0];adjs[0] = edgeno;edgeno++;// i + 1 -> 0, capacity: 0edges[edgeno].v = 0;edges[edgeno].w = 0;edges[edgeno].next = adjs[i + 1];adjs[i + 1] = edgeno;edgeno++;// i + 1 -> N + 1, capacity: Biedges[edgeno].v = N + 1;edges[edgeno].w = Bi;edges[edgeno].next = adjs[i + 1];adjs[i + 1] = edgeno;edgeno++;// N + 1 -> i + 1, capacity: 0edges[edgeno].v = i + 1;edges[edgeno].w = 0;edges[edgeno].next = adjs[N + 1];adjs[N + 1] = edgeno;edgeno++;}for (int i = 0; i < M; ++i){int a, b, w;scanf("%d%d%d", &a, &b, &w);// a -> b, capacity: wedges[edgeno].v = b;edges[edgeno].w = w;edges[edgeno].next = adjs[a];adjs[a] = edgeno;edgeno++;// b -> a, capacity: wedges[edgeno].v = a;edges[edgeno].w = w;edges[edgeno].next = adjs[b];adjs[b] = edgeno;edgeno++;}assert(edgeno <= 2 * MAXN + 2 * MAXM + 2 * MAXN);// printf("[debug]edges(%d):\n", edgeno);// for (int i = 0; i < edgeno; ++i)// {// printf("i: %d, v: %d, w: %d, next: %d, reverse: %d\n", i, edges[i].v, edges[i].w, edges[i].next, edges[i].reverse);// }N += 2;const int source = 0, sink = N - 1;printf("%d\n", dinic(GL, Queue, adjs, edges, N, source, sink));return 0;}


0 0
原创粉丝点击