码迷,mamicode.com
首页 > 其他好文 > 详细

P3171 [CQOI2015]网络吞吐量

时间:2018-02-21 17:09:36      阅读:229      评论:0      收藏:0      [点我收藏+]

标签:blog   front   常用   优先   else   文件   ref   empty   eof   

P3171 [CQOI2015]网络吞吐量https://www.luogu.org/problemnew/show/P3171

题目描述

路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法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


正解思路:最短路+最大流
1.跑出最短路[可能有多条] (貌似DJ比Spfa快??)
2.将所有最短路上的边连到网络流的图上[将u+n节点与v节点连边,容量为inf]
3.拆点,限制流量[将i节点与i+n节点连边,容量为节点的吞吐量] (1节点和n节点连边时的容量置为inf)
4.跑最大流

实现时的难点:
对于步骤2,可以枚举每一条边,如果有dist[u]+w==dist[v],则该边一定在一条最短路上[注意双向都要判断] (试过dfs,不好写,可以过样例,但是会TLE和RE)
实现时的坑点:
inf需要很大,1e9是不够的
#define RG register
#define LL long long
#define inf (1LL<<60)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
const int N=505,NN=2000,M=1e5+5;
inline LL read()
{
    RG LL x=0,w=1;RG char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)w=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)x=x*10+ch-‘0‘,ch=getchar();
    return x*w;
}
inline LL minn(LL a,LL b){return a<b?a:b;}
LL n,m,S,T,Ans,cnt;//源点S为1,汇点T为2*n
LL last[N],dist[N];//last[]是跑最短路建图时所用的邻接表的末指针数组,dist[i]表示节点i到起点1的最短路长度
LL a[M],b[M],c[M];//存储边的信息
LL dep[NN],cur[NN],head[NN];//dep[]为dfs深度,cur[]当前弧,head[]是跑最大流建图时所用的邻接表的末指针数组
bool used[N];//用于跑Spfa
struct edge{
    LL to,next,w;
}e[2*M],ee[3*M];//两个图
inline void insert(LL u,LL v,LL w)//连边[最短路] (双向边)
{
    e[++cnt]=(edge){v,last[u],w};last[u]=cnt;
    e[++cnt]=(edge){u,last[v],w};last[v]=cnt;
}
inline void link(LL u,LL v,LL w)//连边[最大流] (单向边)
{
    ee[++cnt]=(edge){v,head[u],w};head[u]=cnt;
    ee[++cnt]=(edge){u,head[v],0};head[v]=cnt;
}
queue<LL> Q;
inline void Spfa()
{
    for(LL i=1;i<=n;i++)dist[i]=inf;
    dist[1]=0;
    used[1]=true;
    Q.push(1);
    while(!Q.empty())
    {
        LL now=Q.front();Q.pop();
        for(LL i=last[now];i;i=e[i].next)
        {
            LL v=e[i].to;
            if(dist[v]>dist[now]+e[i].w)
            {
                dist[v]=dist[now]+e[i].w;
                if(!used[v])Q.push(v),used[v]=1;
            }
        }
        used[now]=0;
    }
}
inline bool bfs()
{
    while(!Q.empty())Q.pop();
    memset(dep,0,sizeof(dep));
    dep[S]=1;
    Q.push(S);
    while(!Q.empty())
    {
        LL now=Q.front();Q.pop();
        for(LL i=head[now];i;i=ee[i].next)
        {
            LL v=ee[i].to;
            if(ee[i].w>0&&!dep[v])
            {
                dep[v]=dep[now]+1;
                Q.push(v);
            }
        }
    }
    return dep[T]!=0;
}
LL dfs(LL now,LL flow)
{
    if(now==T)return flow;
    for(LL& i=cur[now];i;i=ee[i].next)
    {
        LL v=ee[i].to;
        if(dep[v]==dep[now]+1&&ee[i].w!=0)
        {
            LL di=dfs(v,minn(flow,ee[i].w));
            if(di>0){ee[i].w-=di;ee[i^1].w+=di;return di;}
        }
    }
    return 0;
}
int main()
{
    n=read();
    m=read();
    for(LL i=1;i<=m;i++)
    {
        a[i]=read(),b[i]=read(),c[i]=read();
        insert(a[i],b[i],c[i]);
    }
    Spfa();
    cnt=1;
    for(LL i=1;i<=m;i++)//连边
    {
        if(dist[a[i]]+c[i]==dist[b[i]])link(a[i]+n,b[i],inf);
        if(dist[b[i]]+c[i]==dist[a[i]])link(b[i]+n,a[i],inf);
    }
    for(LL i=1;i<=n;i++)//拆点
    {
        LL x=read();
        if(i==1||i==n)link(i,i+n,inf);
        else link(i,i+n,x);
    }
    S=1;T=2*n;
    while(bfs())
    {
        for(LL i=S;i<=T;i++)cur[i]=head[i];
        while(LL d=dfs(S,inf))Ans+=d;
    }
    printf("%lld\n",Ans);
    return 0;
}

P3171 [CQOI2015]网络吞吐量

标签:blog   front   常用   优先   else   文件   ref   empty   eof   

原文地址:https://www.cnblogs.com/sdzwyq/p/8456851.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!