标签:
Description
Input
Output
Sample Input
3 4 7 2 0 4 2 6 1 2 40 3 2 70 2 3 90 1 3 120
Sample Output
110
题目大意:有n个棚,有m条路,每个棚紧挨着一些牛,每个棚有一定容量。每条路有一个长度,每条路可以同时跑无数条牛。问要让所有牛有棚住,牛中移动距离的最长路最小能有多小?
分析:与前面的题类似,先跑Floyd,然后都是二分,然后跑最大流,直到满足为止。但是这个题建图有一个很困难的地方。就是拆点及拆点的作用。这里把每个棚拆成两个点,负载为INF,关键在于如果两个点u->v可达且路径长度<=mid,那么此时在u的入点连一条边到v的出点。为什么那么奇葩呢,因为转移的量只能转移一次,如果不拆点流量可能转移多次,那么总路径长度将会大于mid。好好体会一下!
另外不知道为什么二分用 while(low<high){ if(...) low=mid+1;else high=mid} 输出low不行,而用ans记录法(见代码)就可以,求大神解答,叩谢!
上代码
<span style="font-size:18px;">#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<queue> using namespace std; const int MAXN = 510; const int MAXM = 330110; const int inf = 0x3f3f3f3f; const long long INF = 1e16; struct Edge { int to, cap, next; }; Edge edge[MAXM]; int level[MAXN]; int head[MAXN]; int cow[MAXN]; int hold[MAXN]; long long dist[MAXN][MAXN]; int src, des, cnt; void addedge( int from, int to, int cap ) { edge[cnt].to = to; edge[cnt].cap = cap; edge[cnt].next = head[from]; head[from] = cnt++; edge[cnt].to = from; edge[cnt].cap = 0; edge[cnt].next = head[to]; head[to] = cnt++; } int bfs( ) { queue<int> q; while (!q.empty( )) q.pop( ); memset( level, -1, sizeof level ); level[src] = 0; q.push( src ); 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].cap > 0 && level[v] == -1) { level[v] = level[u] + 1; q.push( v ); } } } return level[des] != -1; } int dfs( int u, int f ) { if (u == des) return f; int tem; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (edge[i].cap > 0 && level[v] == level[u] + 1) { tem = dfs( v, min( f, edge[i].cap ) ); if (tem > 0) { edge[i].cap -= tem; edge[i ^ 1].cap += tem; return tem; } } } level[u] = -1; return 0; } int Dinic( ) { int ans = 0, tem; while (bfs( )) { while (tem = dfs( src, INF )) { ans += tem; } } return ans; } int main( ) { int n, m; while (cin >> n >> m) { int cows = 0; memset( dist, -1, sizeof dist ); src = 0, des = 501; for (int i = 1; i <= n; i++) { scanf( "%d%d", &cow[i], &hold[i] ); cows += cow[i]; } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) dist[i][j] = INF; } for (int i = 1; i <= m; i++) { int a, b, dis; scanf( "%d%d%d", &a, &b, &dis ); if (dis < dist[a][b]) dist[a][b] = dist[b][a] = dis; } //Floyd for (int k = 1; k <= n; k++) for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (dist[i][j] > dist[i][k] + dist[k][j]) { dist[i][j] = dist[i][k] + dist[k][j]; } long long low = -1, high = INF - 1; long long ans = -1; while (low <= high) { long long mid = (low + high) / 2; memset( head, -1, sizeof head ); cnt = 0; for (int i = 1; i <= n; i++) { addedge( src, i, cow[i] ); addedge( i + 250, des, hold[i] ); addedge( i, i + 250, hold[i] ); } for (int i = 1; i <= n; i++) { for (int j = i + 1; j <= n; j++) { if (dist[i][j] <= mid) { addedge( i, j + 250, inf ); addedge( j, i + 250, inf ); } } } if (Dinic( ) ==cows) { ans = mid; high = mid-1; } else low = mid+1; } cout << ans << endl; } return 0; }</span>
解题报告 之 POJ2391 Ombrophobic Bovines
标签:
原文地址:http://blog.csdn.net/maxichu/article/details/45154663