网络吞吐量

3931: [CQOI2015]网络吞吐量

Time Limit: 10 Sec   Memory Limit: 512 MB

路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法计算最短路径,然后尽量沿最短路径转发数据包。现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数量),假设所有数据包一定沿最短路径转发,试计算从路由器1到路由器n的网络的最大吞吐量。计算中忽略转发及传输的时间开销,不考虑链路的带宽限制,即认为数据包可以瞬间通过网络。路由器1到路由器n作为起点和终点,自身的吞吐量不用考虑,网络上也不存在将1和n直接相连的链路。

Input

输入文件第一行包含两个空格分开的正整数n和m,分别表示路由器数量和链路的数量。网络中的路由器使用1到n编号。接下来m行,每行包含三个空格分开的正整数a、b和d,表示从路由器a到路由器b存在一条距离为d的双向链路。 接下来n行,每行包含一个正整数c,分别给出每一个路由器的吞吐量。

Output

输出一个整数,为题目所求吞吐量。

Sample Input
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
Sample Output
70
Hint

 对于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;  
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值