Gold Transportation
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 3077 | Accepted: 1100 |
Description

Input
The input contains several test cases. For each case, the first line is integer N(1<=N<=200). The second line is N integers associated with the storage of the gold mine in every towns .The third line is also N integers associated with the storage of the storehouses
in every towns .Next is integer M(0<=M<=(n-1)*n/2).Then M lines follow. Each line is three integers x y and d(1<=x,y<=N,0<d<=10000), means that there is a road between x and y for distance of d. N=0 means end of the input.
Output
For each case, output the minimum of the maximum adjacent distance on the condition that all the gold has been transported to the storehouses or "No Solution".
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
O(∩_∩)O~,又1A了。好难得
题意:有N个城市,每个城市都有一个金矿和一个仓库,已给出每个城市金矿的容量以及仓库的空间。
因为一个城市的仓库可能无法容纳该城市的所有金矿,所以需要通过运输方式把多余的金矿存储在其它城市的仓库里面。
现在给你M条无向的运输路线以及路线的长度。问你能不能使得所有金矿都能存储在仓库里面,若不能输出No Solution,否则求出运输过程中(可能不需要运输)所有被使用路线中的最大长度 的最小值。
很好想的思路吧:枚举运输过程中所有被使用路线中的最大长度,根据当前长度建边,跑一次最大流,看是否满流,若满流压缩长度,反之增大长度,然后继续查找。
建图:对当前枚举的mid值,设置超级源点source,超级汇点sink
1,source到所有城市建边,容量为城市的金矿数目;
2,所有城市到sink建边,容量为城市的仓库容量;
3,枚举所有路线,若路线长度小于或等于mid,则建边,容量为INF,因为只要我们愿意,我们可以无限转移两个城市的金矿。
若流入汇点的流量等于源点流出的流量,则说明所有金矿都已经放进仓库。
AC代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define MAXN 210
#define MAXM 100000+10
#define INF 0x3f3f3f3f
using namespace std;
struct Edge
{
int from, to, cap, flow, next;
};
Edge edge[MAXM], Redge[MAXM];
int head[MAXN], Rhead[MAXN], cur[MAXN], edgenum, Redgenum;
int dist[MAXN];
bool vis[MAXN];
int source, sink;//超级源点 超级汇点
int N, M;
int sum;//记录总流量
void init()
{
edgenum = 0;
memset(head, -1, sizeof(head));
}
struct Node
{
int from, to, val;
};
Node node[MAXM];
int nodenum;
void addNode(int u, int v, int w)
{
Node E = {u, v, w};
node[nodenum++] = E;
}
int Max;//记录最大边权
void addEdge(int u, int v, int w)
{
Edge E1 = {u, v, w, 0, head[u]};
edge[edgenum] = E1;
head[u] = edgenum++;
Edge E2 = {v, u, 0, 0, head[v]};
edge[edgenum] = E2;
head[v] = edgenum++;
}
void getMap()
{
source = 0, sink = N+1;
sum = 0;
Max = 0;
int a, b, c;
for(int i = 1; i <= N; i++)
{
scanf("%d", &a);
sum += a;//记录总流量
addEdge(source, i, a);//源点 到 城市i 建边
}
for(int i = 1; i <= N; i++)
{
scanf("%d", &a);
addEdge(i, sink, a);
}
scanf("%d", &M);
nodenum = 0;
while(M--)
{
scanf("%d%d%d", &a, &b, &c);
addNode(a, b, c);//用邻接表建边 怕有重边
addNode(b, a, c);
Max = max(Max, c);//更新最大边权
}
}
void addnew(int mid)
{
for(int i = 0; i < nodenum; i++)
{
Node E = node[i];
if(E.val <= mid)
addEdge(E.from, E.to, INF);//建无穷大的边
}
}
bool BFS(int s, int t)
{
queue<int> Q;
memset(dist, -1, sizeof(dist));
memset(vis, false, sizeof(vis));
dist[s] = 0;
vis[s] = true;
Q.push(s);
while(!Q.empty())
{
int u = Q.front();
Q.pop();
for(int i = head[u]; i != -1; i = edge[i].next)
{
Edge E = edge[i];
if(!vis[E.to] && E.cap > E.flow)
{
dist[E.to] = dist[u] + 1;
if(E.to == t) return true;
vis[E.to] = true;
Q.push(E.to);
}
}
}
return false;
}
int DFS(int x, int a, int t)
{
if(x == t || a == 0) return a;
int flow = 0, f;
for(int &i = cur[x]; i != -1; i = edge[i].next)
{
Edge &E = edge[i];
if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap - E.flow), t)) > 0)
{
edge[i].flow += f;
edge[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Maxflow(int s, int t)
{
int flow = 0;
while(BFS(s, t))
{
memcpy(cur, head, sizeof(head));
flow += DFS(s, INF, t);
}
return flow;
}
void solve()
{
int left = 0, right = Max, mid;//最大边权作为区间右端点
int ans = INF;
memcpy(Redge, edge, sizeof(edge));
memcpy(Rhead, head, sizeof(head));
Redgenum = edgenum;
while(right >= left)
{
mid = (left + right) >> 1;
memcpy(edge, Redge, sizeof(Redge));
memcpy(head, Rhead, sizeof(Rhead));
edgenum = Redgenum;
addnew(mid);
if(Maxflow(source, sink) == sum)//满流才满足条件
{
ans = min(ans, mid);
right = mid - 1;
}
else
left = mid + 1;
}
if(ans == INF)
printf("No Solution\n");
else
printf("%d\n", ans);
}
int main()
{
while(scanf("%d", &N), N)
{
init();
getMap();
solve();
}
return 0;
}