zoukankan      html  css  js  c++  java
  • [CQOI2015]网络吞吐量(网络流+SPFA)

    [CQOI2015]网络吞吐量

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

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

    输入输出样例

    输入样例#1:

    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

    输出样例#1:

    70

    说明

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

    一道比较鬼的题目,很容易出兮兮,题目描述的有些不太清楚吧。
    这道题是会有重边的,数组开小了会出现莫名其妙的错误。
    那么进入正题吧。
    这道题目大致思路还是很容易看出来,最短路,然后通过在最短路的边上跑最大流。
    考虑如何建边,首先可选的边可这样判断

    dis[x]+v==dis[y](v表示边权)

    然后这里网络流建图的话,因为限制在点权上面,所以我们运用经典的拆点思想把一个点拆成两个点建边,跑一遍网络流即可。
    注意long long

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #define lll long long
    using namespace std;
    lll read()
    {
        lll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    lll n,m,cnt,inf=(1ll<<40),s,t;
    lll head[1010],a[510],x[100010],y[100010],z[100010];
    struct node{
        lll v,to,next;
    }edge[400010];
    void add(lll p,lll q,lll w)
    {
        cnt++;
        edge[cnt].to=q;
        edge[cnt].v=w;
        edge[cnt].next=head[p];
        head[p]=cnt;
    }
    lll vis[510],team[200010],dis[510];
    void spfa();
    lll deep[1010];
    bool bfs();
    lll dfs(lll,lll);
    int main()
    {
        n=read();m=read();
        s=1;t=2*n;
        for(lll i=1;i<=m;i++)
        {
            x[i]=read();y[i]=read();z[i]=read();
            add(x[i],y[i],z[i]);add(y[i],x[i],z[i]);
        }
        for(lll i=1;i<=n;i++)
        {
            a[i]=read();
        }
        a[1]=inf;a[n]=inf;
        spfa();
        cnt=1;
        memset(head,0,sizeof(head));
        for(lll i=1;i<=n;i++)
        {
            add(i*2-1,i*2,a[i]);
            add(i*2,i*2-1,a[i]);
        }
        for(lll i=1;i<=m;i++)
        {
            if(dis[x[i]]+z[i]==dis[y[i]])
            {
                add(x[i]*2,y[i]*2-1,inf);
                add(y[i]*2-1,x[i]*2,0);
            }
            else if(dis[y[i]]+z[i]==dis[x[i]])
            {
                add(y[i]*2,x[i]*2-1,inf);
                add(x[i]*2-1,y[i]*2,0);
            }
        }
        lll d=0,ans=0;
        while(bfs())
        {
            d=dfs(s,inf);
            while(d>0)
            {
                //cout<<d<<endl;
                ans+=d;d=dfs(s,inf);
            }
        }
        cout<<ans;
    }
    void spfa()
    {
        for(int i=1;i<=n;i++)
        dis[i]=(1ll<<40);
        lll u,v,l=0,r=1;
        team[1]=1;vis[1]=1;dis[1]=0;
        while(l<r)
        {
            l++;
            u=team[l];
            vis[u]=0;
            for(lll i=head[u];i;i=edge[i].next)
            {
                v=edge[i].to;
                if(dis[v]>dis[u]+edge[i].v)
                {
                    dis[v]=dis[u]+edge[i].v;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        team[++r]=v;
                    }
                }
            }
        }
    }
    bool bfs()
    {
        memset(deep,0,sizeof(deep));
        memset(team,0,sizeof(team));
        lll u,v,l=0,r=1;
        team[1]=s;deep[s]=1;
        while(l<r)
        {
            l++;
            u=team[l];
            for(lll i=head[u];i;i=edge[i].next)
            {
                v=edge[i].to;
                if(deep[v]||edge[i].v<=0) continue;
                deep[v]=deep[u]+1;
                r++;
                team[r]=v;
            }
        }
        if(deep[t]) return true;
        return false;
    }
    lll dfs(lll k,lll w)
    {
        if(k==t) return w;
        lll u,v,d=0;
        for(lll i=head[k];i;i=edge[i].next)
        {
            v=edge[i].to;
            if(deep[v]==deep[k]+1&&edge[i].v>0)
            {
                d=dfs(v,min(edge[i].v,w));
                if(d>0)
                {
                    edge[i].v-=d;
                    edge[i^1].v+=d;
                    return d;
                }
            }
        }
        if(d==0) deep[k]=0;return 0;
    }
    
  • 相关阅读:
    iOS 相册相机应用2
    运行时啊
    在iOS开发的Quartz2D使用中实现图片剪切和截屏功能
    内购
    自制数据挖掘工具分析北京房价 (二) 数据清洗
    数据挖掘工具分析北京房价 (一) 数据爬取采集
    程序员讨论 《黑客帝国》 (三) 情感
    程序员讨论《黑客帝国》(二)平衡和进化
    程序员讨论《黑客帝国》(一)真实与虚拟
    类库与框架,强类型与弱类型的闲聊
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9187674.html
Copyright © 2011-2022 走看看