• 洛谷 P3171 [CQOI2015]网络吞吐量 解题报告


    P3171 [CQOI2015]网络吞吐量

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    说明

    对于100%的数据,n<=500,m<=100000,d,c<=10^9


    get到题意是第一步,最短路径其实只需要1-n的就可以了。

    我们先正反做一编最短路,把所有在最短路上的边抽出来建新图。

    把每个点拆开,边权为点的吞吐量,其余边只是保证联通性,故置inf即可


    Code:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <queue>
    #define ll long long
    using namespace std;
    #define P pair <ll ,int >
    const int N=502;
    const int M=200010;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int n,m,used[N];
    ll diss[N],dist[N],inout[N],edge0[M],edge[M<<1];
    int head0[N],to0[M],Next0[M],cnt0;
    void add0(int u,int v,ll w)
    {
        to0[++cnt0]=v;Next0[cnt0]=head0[u];edge0[cnt0]=w;head0[u]=cnt0;
    }
    int head[N<<1],to[M<<1],Next[M<<1],cnt=1;
    void add(int u,int v,ll w)
    {
        to[++cnt]=v;Next[cnt]=head[u];edge[cnt]=w;head[u]=cnt;
    }
    priority_queue <P,vector<P >,greater<P > >  q0;
    P p;
    void disj()
    {
        memset(diss,0x3f,sizeof(diss));
        memset(used,0,sizeof(used));
        diss[1]=0;
        p.first=0,p.second=1;
        q0.push(p);
        while(!q0.empty())
        {
            int u=q0.top().second;
            q0.pop();
            if(used[u]) continue;
            used[u]=1;
            for(int i=head0[u];i;i=Next0[i])
            {
                int v=to0[i];
                ll w=edge0[i];
                if(diss[v]>diss[u]+w)
                {
                    diss[v]=diss[u]+w;
                    p.first=diss[v],p.second=v;
                    q0.push(p);
                }
            }
        }
        memset(dist,0x3f,sizeof(diss));
        memset(used,0,sizeof(used));
        dist[n]=0;
        p.first=0,p.second=n;
        q0.push(p);
        while(!q0.empty())
        {
            int u=q0.top().second;
            q0.pop();
            if(used[u]) continue;
            used[u]=1;
            for(int i=head0[u];i;i=Next0[i])
            {
                int v=to0[i];
                ll w=edge0[i];
                if(dist[v]>dist[u]+w)
                {
                    dist[v]=dist[u]+w;
                    p.first=dist[v],p.second=v;
                    q0.push(p);
                }
            }
        }
    }
    void New()
    {
        for(int i=1;i<=n;i++)
        {
            add(i,i+n,inout[i]);
            add(i+n,i,0);
            for(int j=head0[i];j;j=Next0[j])
            {
                int v=to0[j];
                ll w=edge0[j];
                if(diss[i]+dist[v]+w==diss[n])
                {
                    add(i+n,v,inf);
                    add(v,i+n,0);
                    //printf("%d %d %lld
    ",i,v,inout[v]);
                }
            }
        }
    }
    void init()
    {
        scanf("%d%d",&n,&m);
        int u,v;ll w;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%lld",&u,&v,&w);
            add0(u,v,w),add0(v,u,w);
        }
        for(int i=1;i<=n;i++)
            scanf("%lld",inout+i);
        inout[1]=inf;
        inout[n]=inf;
        disj();
        New();
    }
    int dep[N<<1];
    queue <int > q;
    bool bfs()
    {
        memset(dep,0,sizeof(dep));
        dep[1]=1;
        while(!q.empty()) q.pop();
        q.push(1);
        while(!q.empty())
        {
            int u=q.front();
            q.pop();
            for(int i=head[u];i;i=Next[i])
            {
                int v=to[i];
                ll w=edge[i];
                if(w&&!dep[v])
                {
                    dep[v]=dep[u]+1;
                    if(v==n*2) return 1;
                    q.push(v);
                }
            }
        }
        return 0;
    }
    ll dfs(int now,ll flow)
    {
        if(now==n*2) return flow;
        ll k,rest=flow;
        for(int i=head[now];i&&rest;i=Next[i])
        {
            int v=to[i];
            if(edge[i]&&dep[v]==dep[now]+1)
            {
                k=dfs(v,min(rest,edge[i]));
                if(!k) dep[v]=0;
                edge[i]-=k;
                edge[i^1]+=k;
                rest-=k;
            }
        }
        return flow-rest;
    }
    void work()
    {
        ll flow=0,maxflow=0;
        while(bfs())
            while(flow=dfs(1,inf))
                maxflow+=flow;
        printf("%lld
    ",maxflow);
    }
    int main()
    {
        init();
        work();
        return 0;
    }
    
    

    2018.7.7

  • 相关阅读:
    第三章 套接字编程简介
    Effective STL 学习关于容器
    C++单例模板
    第六章 IO复用:select和poll函数
    第五章 TCP客户服务器程序示例
    八、基本UDP套接字编程
    第四章 基本TCP套接字编程
    测试 LaTeX
    如何在不支持 LaTeX 的环境使用 LaTeX 命令输入公式?
    Ubuntu 下 Wine 安装微软 Office
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9277382.html
Copyright © 2020-2023  润新知