Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 3079 | Accepted: 1101 |
Description
Input
Output
Sample Input
4 3 2 0 0 0 0 3 3 6 1 2 4 1 3 10 1 4 12 2 3 6 2 4 8 3 4 5 0
Sample Output
6
题意:
题意:有N个城市,每个城市都有一个金矿和一个仓库,已给出每个城市金矿的容量以及仓库的空间。
因为一个城市的仓库可能无法容纳该城市的所有金矿,所以需要通过运输方式把多余的金矿存储在其它城市的仓库里面。
现在给你M条无向的运输路线以及路线的长度。问你能不能使得所有金矿都能存储在仓库里面,若不能输出No Solution,否则求出运输过程中(可能不需要运输)所有被使用路线中的最大长度 的最小值。
解析:又是最大值的最小值,好把,二分走起。二分枚举使用路线的最大长度mid,再枚举每一条边,边的权值满足 <= mid 的边加入新图,然后跑最大流,看是否满流,满流的话减少mid, 反之增加mid,最后得到就是所有被使用路线中的最大长度 的最小值。
具体建图过程:
(1)建立超级源点0, 超级汇点n + 1.
(2)汇点到每一个城市建边,权值为每个城市金矿的数量。
(3)枚举每一条边,边的权值满足 <= mid 的建边,权值为INF
(4)每个城市到汇点建边,权值为每个城市仓库的数量。
#include <cstdio> #include <cstring> #include <algorithm> #include <queue> #define maxn 1000 #define maxm 100000 #define INF 0x3f3f3f3f using namespace std; int n, m; int a[maxn];//每个城市的金矿数量 int b[maxn];//每个城市的仓库数量 struct NODE{ int u, v, w, next; }; NODE map[maxm]; int head1[maxn], cnt1; void initmap(){ cnt1 = 0; memset(head1, -1, sizeof(head1)); } void addmap(int u ,int v, int w){ map[cnt1].u = u; map[cnt1].v = v; map[cnt1].w = w; map[cnt1].next = head1[u]; head1[u] = cnt1++; } int maxs; int sum; void input(){ sum = maxs = 0; initmap(); for(int i = 1; i <= n; ++i){ scanf("%d", &a[i]); sum += a[i]; } for(int i = 1; i <= n ;++i){ scanf("%d", &b[i]); } scanf("%d", &m); while(m--){ int a, b, c; scanf("%d%d%d", &a, &b, &c); maxs = max(maxs, c); addmap(a, b, c); addmap(b, a, c); } } struct node{ int u, v, cap, flow, next; }; node edge[maxm]; int head[maxn], cnt, cur[maxn]; int vis[maxn], dist[maxn]; void initedge(){ cnt = 0; memset(head, -1, sizeof(head)); } void addedge(int u, int v, int w){ edge[cnt].u = u; edge[cnt].v = v; edge[cnt].cap = w; edge[cnt].flow = 0; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].u = v; edge[cnt].v = u; edge[cnt].cap = 0; edge[cnt].flow = 0; edge[cnt].next = head[v]; head[v] = cnt++; } void getmap(int ans){ for(int i = 1; i <= n; ++i){ addedge(0, i, a[i]); addedge(i, n + 1, b[i]); } for(int i = 0; i < cnt1; ++i) if(map[i].w <= ans) addedge(map[i].u, map[i].v, INF); } bool BFS(int st ,int ed){ queue<int>q; memset(vis, 0 ,sizeof(vis)); memset(dist, -1, sizeof(dist)); vis[st] = 1; dist[st] = 0; q.push(st); while(!q.empty()){ int u = q.front(); q.pop(); for(int i = head[u]; i != -1; i = edge[i].next){ node E = edge[i]; if(!vis[E.v] && E.cap > E.flow){ vis[E.v] = 1; dist[E.v] = dist[u] + 1; if(E.v == ed) return true; q.push(E.v); } } } return false; } int DFS(int x, int ed, int a){ if(x == ed || a == 0) return a; int flow = 0, f; for(int &i = cur[x]; i != -1; i = edge[i].next){ node &E = edge[i]; if(dist[E.v] == dist[x] + 1 && (f = DFS(E.v, ed, min(a, E.cap - E.flow))) > 0){ E.flow += f; edge[i ^ 1].flow -= f; a -= f; flow += f; if(a == 0) break; } } return flow; } int maxflow(int st, int ed){ int flowsum = 0; while(BFS(st,ed)){ memcpy(cur, head, sizeof(head)); flowsum += DFS(st, ed, INF); } return flowsum; } int main (){ while(scanf("%d", &n), n){ input(); int l = 0, r = maxs, mid; int max_min = maxs; while(r > l){ mid = (l + r) / 2; initedge(); getmap(mid); if(maxflow(0, n + 1) == sum){ max_min = min(max_min, mid); r = mid; } else l = mid + 1; } if(max_min == maxs) printf("No Solution\n"); else printf("%d\n", max_min); } return 0; }