【bzoj3931】【CQOI2015】【网络吞吐量】【spfa+最大流】

来源:互联网 发布:淘宝客推广联盟教程 编辑:程序博客网 时间:2024/06/05 11:48

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

题解:建出最短路图之后拆点跑最大流即可.

代码:

#include<iostream>#include<cstdio>#include<cstring>#define N 510#define M 100010#define ll long long#define inf 12345678987654321llusing namespace std;int n,x,y,v,m,cnt,T,num=1,f[N],q[N*20],next[M<<2],point[N];int cur[N<<1],d[N<<1],head[N<<1],gap[N<<1],pre[N<<1];long long dis[N],a[N];struct use{  int st,en;  long long v;}e[M<<1],b[M<<1];int read(){  int x(0);char ch=getchar();  while (ch<'0'||ch>'9') ch=getchar();  while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();  return x; }void add(int x,int y,ll v){  //cout<<"!"<<x<<' '<<y<<' '<<v<<endl;  next[++cnt]=point[x];point[x]=cnt;  e[cnt].st=x;e[cnt].en=y;e[cnt].v=v;}void ins(int x,int y,ll v){    //cout<<x<<' '<<y<<' '<<v<<endl;  next[++num]=head[x];head[x]=num;  b[num].st=x;b[num].en=y;b[num].v=v;  next[++num]=head[y];head[y]=num;  b[num].st=y;b[num].en=x;b[num].v=0;}void spfa(){  int h(0),t(1);  memset(dis,127,sizeof(dis));  q[t]=1;dis[1]=0;f[1]=1;  while (h<t){    int u=q[++h];f[u]=0;    for (int i=point[u];i;i=next[i])      if (dis[e[i].en]>dis[u]+e[i].v){         dis[e[i].en]=dis[u]+e[i].v;        if (!f[e[i].en]){          f[e[i].en]=1;          q[++t]=e[i].en;        }      }  }}ll isap(){  int u(1),i;  ll ans(0);gap[0]=T;  for (int i=1;i<=T;i++) cur[i]=head[i];  while(d[1]<T){    bool f(0);    for (i=cur[u];i;i=next[i])       if (d[b[i].en]+1==d[u]&&b[i].v){f=1;cur[u]=i;break;}    if (f){      pre[u=b[i].en]=i;      if (u==T){        ll mn=inf;        for (int i=T;i!=1;i=b[pre[i]].st) mn=min(mn,b[pre[i]].v);        ans+=mn;        for (int i=T;i!=1;i=b[pre[i]].st) b[pre[i]].v-=mn,b[pre[i]^1].v+=mn;        u=1;      }    }    else{      --gap[d[u]];if (!gap[d[u]]) return ans;      int mn=T;      for (i=head[u];i;i=next[i])        if (b[i].v) mn=min(mn,d[b[i].en]);      gap[d[u]=mn+1]++;cur[u]=head[u];if (u!=1) u=b[pre[u]].st;     }  }  return ans;}int main(){  n=read();m=read();  for (int i=1;i<=m;i++){    x=read();y=read();v=read();    add(x,y,v);add(y,x,v);  }       spfa();memset(next,0,sizeof(next));  for (int i=1;i<=n;i++) a[i]=(ll)read();a[1]=a[n]=inf;  for (int i=1;i<=n;i++) ins(i,i+n,a[i]);  for (int i=1;i<=cnt;i++)    if (dis[e[i].en]==dis[e[i].st]+e[i].v)       ins(e[i].st+n,e[i].en,inf);        T=n+n;  cout<<isap();} 


0 0