3931: [CQOI2015]网络吞吐量
Time Limit: 10 Sec Memory Limit: 512 MB路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法计算最短路径,然后尽量沿最短路径转发数据包。现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数量),假设所有数据包一定沿最短路径转发,试计算从路由器1到路由器n的网络的最大吞吐量。计算中忽略转发及传输的时间开销,不考虑链路的带宽限制,即认为数据包可以瞬间通过网络。路由器1到路由器n作为起点和终点,自身的吞吐量不用考虑,网络上也不存在将1和n直接相连的链路。
输入文件第一行包含两个空格分开的正整数n和m,分别表示路由器数量和链路的数量。网络中的路由器使用1到n编号。接下来m行,每行包含三个空格分开的正整数a、b和d,表示从路由器a到路由器b存在一条距离为d的双向链路。 接下来n行,每行包含一个正整数c,分别给出每一个路由器的吞吐量。
输出一个整数,为题目所求吞吐量。
7 10 1 2 2 1 5 2 2 4 1 2 3 3 3 7 1 4 5 4 4 3 1 4 6 1 5 6 2 6 7 1 1 100 20 50 20 60 1
70
对于100%的数据,n≤500,m≤100000,d,c≤10^9
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 400009
#define inf ((1LL<<63)-1)
#define ll long long
using namespace std;
ll head[maxn], nextx[maxn], point[maxn], now, p[maxn], flow[maxn];
ll n, m, value[maxn], dist[maxn], dis[maxn], x[maxn], y[maxn], v[maxn];
void add(ll x, ll y, ll v)
{
nextx[++now] = head[x];
head[x] = now;
point[now] = y;
value[now] = v;
}
void add2(ll x, ll y, ll v)
{
nextx[++now] = head[x];
head[x] = now;
point[now] = y;
flow[now] = v;
nextx[++now] = head[y];
head[y] = now;
point[now] = x;
flow[now] = 0;
}
void spfa(ll s)
{
memset(dist, -1, sizeof(dist));
int visit[maxn] = {0};
visit[s] = 1;
queue<ll>q;
q.push(s);
dist[s] = 0;
while (!q.empty())
{
int u = q.front();
q.pop();
visit[u] = 0;
for (int i = head[u]; i; i = nextx[i])
{
ll k = point[i];
if (dist[k] == -1 || dist[u] + value[i] < dist[k])
{
dist[k] = dist[u] + value[i];
p[k] = u;
if (!visit[k])
{
visit[k] = 1;
q.push(k);
}
}
}
}
}
int bfs(ll s, ll t)
{
queue<ll>q;
memset(dis, -1, sizeof(dis));
q.push(s);
dis[s] = 0;
while (!q.empty())
{
ll u = q.front();
q.pop();
for (int i = head[u]; i; i = nextx[i])
{
ll k = point[i];
if (dis[k] == -1 && flow[i])
{
dis[k] = dis[u] + 1;
q.push(k);
}
}
}
return dis[t] != -1;
}
ll dfs(ll s, ll d, ll t)
{
if (s == t)
{
return d;
}
ll res = 0;
for (int i = head[s]; i && res < d; i = nextx[i])
{
ll u = point[i];
if (flow[i] && dis[u] == dis[s] + 1)
{
ll dd = dfs(u, min(flow[i], d - res), t);
if (dd)
{
flow[i] -= dd;
flow[((i - 1) ^ 1) + 1] += dd;
res += dd;
}
}
}
if (res == 0)
{
dis[s] = -1;
}
return res;
}
int main()
{
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= m; i++)
{
scanf("%lld%lld%lld", &x[i], &y[i], &v[i]);
add(x[i], y[i], v[i]);
add(y[i], x[i], v[i]);
}
spfa(1);
memset(head, 0, sizeof(head));
now = 0;
for (int i = 1; i <= m; i++)
{
if (dist[x[i]] + v[i] == dist[y[i]])
{
add2(x[i] + n, y[i], inf);
}
if (dist[y[i]] + v[i] == dist[x[i]])
{
add2(y[i] + n, x[i], inf);
}
}
ll b;
for (int i = 1; i <= n; i++)
{
scanf("%lld", &b);
add2(i, i + n, (i == 1 || i == n) ? inf : b);
}
ll ans = 0;
while (bfs(1 , n + n))
{
ans += dfs(1 , inf , n + n);
}
printf("%lld\n", ans);
return 0;
}