POJ 2455 解题报告

来源:互联网 发布:贩卖数据 编辑:程序博客网 时间:2024/05/21 18:33

这道题是最大流(maxflow)题。要点在于用二分搜索(binary search)限制边的最大长度(即可以想象为比这个最大长度还长的边不存在)。这样逐步逼近边长的最佳限制,保证只利用小于等于此边长的边就可以从0到N-1 T次,而且每条边只使用1次(capacity = 1)。

这里使用了之前dinic的模板。

测试数据在这里:http://contest.usaco.org/FEB05_6.htm 不谢。

thestoryofsnow2455Accepted1888K829MSC++5297B

/* ID: thestor1 LANG: C++ TASK: poj2455 */#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 MAXP = 40000;const int MAXN = 200;const int INF = numeric_limits<int>::max();class Edge{public:// edge (`u` -> `v`) with capacity `w` and length `l`// `ow` is the original capacity, needed as we run maxflow multiple times here.int v, w, l, ow;// 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->l = -1;this->ow = -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, const int threshold){// 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 && edges[e].l <= threshold){GL[v] = GL[u] + 1;rear++;assert (rear < N);Queue[rear] = v;}// set as next node in adjacent liste = edges[e].next;}}return GL[sink] > 0;}int DFS(int u, int low, int GL[], int adjs[], Edge edges[], const int sink, const int threshold){// 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 && edges[e].l <= threshold){int flow = DFS(v, min(low, edges[e].w), GL, adjs, edges, sink, threshold);// 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, const int threshold){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, threshold)){// 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, INF, GL, adjs, edges, sink, threshold);}return maxflow;}// for directed graph, the reverse edge (v -> u) should have capacity 0// as it is only available after there is flow from u -> v// But for undirected graph, capacities from both directions should have capacity wvoid addEdge(Edge edges[], int &edgeno, int adjs[], int u, int v, int w, int l){// u -> v, capacity: wedges[edgeno].v = v;edges[edgeno].w = w;edges[edgeno].l = l;edges[edgeno].ow = w;edges[edgeno].next = adjs[u];adjs[u] = edgeno;edgeno++;// v -> u, capacity: wedges[edgeno].v = u;edges[edgeno].w = w;edges[edgeno].l = l;edges[edgeno].ow = w;edges[edgeno].next = adjs[v];adjs[v] = edgeno;edgeno++;}int main(){Edge edges[2 * MAXP];int edgeno = 0;int adjs[MAXN];int GL[MAXN];int Queue[MAXN];int lengths[MAXP];int N, P, T;scanf("%d%d%d", &N, &P, &T);memset(adjs, -1, N * sizeof(int));for (int i = 0; i < P; ++i){int A, B, L;scanf("%d%d%d", &A, &B, &L);A--, B--;addEdge(edges, edgeno, adjs, A, B, 1, L);lengths[i] = L;}// printf("[debug]edges(%d):\n", edgeno);// for (int i = 0; i < edgeno; ++i)// {// printf("i: %d, v: %d, w: %d, l: %d, next: %d, reverse: %d\n", i, edges[i].v, edges[i].w, edges[i].l, edges[i].next, i ^ 1);// }sort(lengths, lengths + P);int left = 0, right = P - 1, mid;while (left <= right){mid = (left + right) / 2;int threshold = lengths[mid];// set edges with their original capacities // as we are running maxflow multiple times// and their capacities have been changed by last runfor (int i = 0; i < edgeno; ++i){edges[i].w = edges[i].ow;}int mf = dinic(GL, Queue, adjs, edges, N, 0, N - 1, threshold);if (mf >= T){right = mid - 1;}else{left = mid + 1;}}printf("%d\n", lengths[left]);return 0;}


0 0
原创粉丝点击