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

    Description

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

    Solution

    首先要把最短路的网络建出来,如何建网?

    跑一边SPFA,对于一条边u->v,如果dis[u]+e[i].dis==dis[v],那么这条路就在最短路网中。

    建完网后,因为限制流量于点上而不是边上,所以要拆点为边

    (如 ——@——   ->  ——O——a——O——)

    连向点a的就连在a左边的点,从a出发的就从a右边的点连出 (可以分别命名为 a,a+n)

    从而连接a,a+n的边流量限制为 给定条件,其他边都为INF。

    此题请注意值的大小!,务必开long long,inf要开大 (第一遍WA成0分)

    Code

      1 #include<queue>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define ll long long
      7 #define RG register ll
      8 #define rep(i,a,b)    for(RG i=a;i<=b;i++)
      9 #define per(i,a,b)    for(RG i=a;i>=b;i--)
     10 #define inf (1ll<<60)
     11 #define maxn 2005
     12 #define maxm 100005
     13 using namespace std;
     14 ll n,m,ct,cnt=1,S,T;
     15 ll hd[maxn],head[maxn],step[maxn],dis[maxn],vis[maxn];
     16 struct Edge{
     17     ll u,v,val,next;
     18 }edge[maxm<<1];
     19 struct E{
     20     ll v,next,fl;
     21 }e[maxm<<2];
     22 inline ll read()
     23 {
     24     ll x=0,f=1;char c=getchar();
     25     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     26     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     27     return x*f;
     28 }
     29 
     30 inline void ad(ll u,ll v,ll val)
     31 {
     32     edge[++ct].u=u,edge[ct].v=v,edge[ct].val=val,edge[ct].next=hd[u],hd[u]=ct,swap(u,v);
     33     edge[++ct].u=u,edge[ct].v=v,edge[ct].val=val,edge[ct].next=hd[u],hd[u]=ct;
     34 }
     35 
     36 inline void add(ll u,ll v,ll fl)
     37 {
     38     e[++cnt].v=v,e[cnt].fl=fl,e[cnt].next=head[u],head[u]=cnt,swap(u,v);
     39     e[++cnt].v=v,e[cnt].fl=0 ,e[cnt].next=head[u],head[u]=cnt;
     40 }
     41 
     42 void SPFA()
     43 {
     44     queue<ll> que;
     45     memset(dis,63,sizeof(dis));
     46     dis[1]=0,que.push(1);
     47     RG u,v;
     48     while(!que.empty())
     49     {
     50         u=que.front(),que.pop();vis[u]=0;
     51         for(RG i=hd[u];i;i=edge[i].next)
     52         {
     53             v=edge[i].v;
     54             if(dis[v]>dis[u]+edge[i].val)
     55             {
     56                 dis[v]=dis[u]+edge[i].val;
     57                 if(!vis[v])    vis[v]=1,que.push(v);
     58             }
     59         }
     60     }
     61 }
     62 
     63 ll bfs()
     64 {
     65     queue<ll> que;
     66     memset(step,-1,sizeof(step));step[S]=0,que.push(S);
     67     RG u,v;
     68     while(!que.empty())
     69     {
     70         u=que.front(),que.pop();
     71         for(RG i=head[u];i;i=e[i].next)
     72         {
     73             v=e[i].v;
     74             if(e[i].fl>0&&step[v]==-1)
     75                 step[v]=step[u]+1,que.push(v);
     76         }
     77     }
     78     return (step[T]!=-1);
     79 }
     80 
     81 ll dfs(ll u,ll res)
     82 {
     83     if(u==T||!res)    return res;
     84     ll rem=res;
     85     for(ll i=head[u];i;i=e[i].next)
     86     {
     87         ll v=e[i].v;
     88         if(step[v]==step[u]+1&&e[i].fl>0)
     89         {
     90             ll fl=dfs(v,min(rem,e[i].fl));
     91             e[i].fl-=fl,e[i^1].fl+=fl;
     92             rem-=fl;
     93             if(!rem)    break;
     94         }
     95     }
     96     if(rem)    step[u]=-1;
     97     return res-rem;
     98 }
     99 
    100 void Dinic()
    101 {
    102     ll ans=0;
    103     while(bfs())
    104         ans+=dfs(S,inf);
    105     printf("%lld",ans);
    106 }
    107 
    108 int main()
    109 {
    110     n=read(),m=read(),S=1,T=(n<<1);
    111     RG u,v,val;
    112     rep(i,1,m) u=read(),v=read(),val=read(),ad(u,v,val);
    113     SPFA();
    114     rep(i,1,ct)
    115     {
    116         u=edge[i].u,v=edge[i].v;
    117         if(dis[u]+edge[i].val==dis[v])
    118             add(u+n,v,inf);
    119     }
    120     read();add(1,1+n,inf),add(n,n<<1,inf);
    121     rep(i,2,n-1)
    122         val=read(),add(i,i+n,val);
    123     read();
    124     Dinic();
    125     return 0;
    126 }
    >>点击查看代码<<
  • 相关阅读:
    数据结构——二叉树创建及遍历
    数据结构——二叉树基础
    数据结构——树
    C++拷贝构造函数
    链表C语言实现
    hrbust-oj 1937 神奇的进制转换
    UVALive 6736 Army Formation (容斥原理)
    POJ 2888 Magic Bracelet (Burnside + 矩阵加速dp)
    UVA 10601 Cubes (Burnside引理)
    UVA 11255 Necklace (BurnSide定理)
  • 原文地址:https://www.cnblogs.com/ibilllee/p/8711377.html
Copyright © 2011-2022 走看看