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
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
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 }