[BZOJ 3931][CQOI2015]网络吞吐量(SPFA+网络流)
Description
路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点。网络中实现路由转发的硬件设备称为路由器。为了使数据包最快的到达目的地,路由器需要选择最优的路径转发数据包。例如在常用的路由算法OSPF(开放式最短路径优先)中,路由器会使用经典的Dijkstra算法计算最短路径,然后尽量沿最短路径转发数据包。现在,若已知一个计算机网络中各路由器间的连接情况,以及各个路由器的最大吞吐量(即每秒能转发的数据包数量),假设所有数据包一定沿最短路径转发,试计算从路由器1到路由器n的网络的最大吞吐量。计算中忽略转发及传输的时间开销,不考虑链路的带宽限制,即认为数据包可以瞬间通过网络。路由器1到路由器n作为起点和终点,自身的吞吐量不用考虑,网络上也不存在将1和n直接相连的链路。
Solution
裸题?
先求最短路看哪些边会被用到,拆点跑一下网络流
(虽然说了“会使用经典的Dijkstra算法计算最短路径”,我还是万年SPFA)
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<queue> #include<vector> #define INF 1LL<<60 using namespace std; typedef long long LL; vector<int>G[505]; int n,m,s,t,head1[505],head2[1005],level[1005],cnt1=0,cnt2=0; LL dis[505]; bool inq[505]; struct Node { int next,to; LL w; }Edges1[200005],Edges2[500005]; LL read() { LL x=0,f=1;char c=getchar(); while(c<'0'||c>'9'){ if(c=='-')f=-1;c=getchar(); } while(c>='0'&&c<='9'){ x=x*10+c-'0';c=getchar(); } return x*f; } void addedge1(int u,int v,LL w) { Edges1[cnt1].next=head1[u]; head1[u]=cnt1; Edges1[cnt1].to=v; Edges1[cnt1++].w=w; } void addedge2(int u,int v,LL w) { Edges2[cnt2].next=head2[u]; head2[u]=cnt2; Edges2[cnt2].to=v; Edges2[cnt2++].w=w; } void insert(int u,int v,LL w) { addedge2(u,v,w); addedge2(v,u,0); } queue<int>q; void SPFA() { for(int i=1;i<=n;i++)dis[i]=INF; q.push(1);inq[1]=1,dis[1]=0; while(!q.empty()) { int u=q.front(); q.pop(),inq[u]=0; for(int i=head1[u];~i;i=Edges1[i].next) { int v=Edges1[i].to; if(dis[v]>=dis[u]+Edges1[i].w) { dis[v]=dis[u]+Edges1[i].w; G[u].push_back(i),G[v].push_back(i); if(!inq[v]) inq[v]=1,q.push(v); } } } } bool bfs() { memset(level,-1,sizeof(level)); level[s]=0;q.push(s); while(!q.empty()) { int u=q.front();q.pop(); for(int i=head2[u];~i;i=Edges2[i].next) { int v=Edges2[i].to; if(Edges2[i].w&&level[v]==-1) level[v]=level[u]+1,q.push(v); } } if(level[t]==-1)return false; return true; } LL dfs(int u,LL f) { if(u==t)return f; LL flow=0,d; for(int i=head2[u];~i&&flow<f;i=Edges2[i].next) { int v=Edges2[i].to; if(level[v]==level[u]+1&&Edges2[i].w) { d=dfs(v,min(Edges2[i].w,f-flow)); flow+=d; Edges2[i].w-=d; Edges2[i^1].w+=d; } } if(!flow)level[u]=-1; return flow; } void Dinic() { LL res=0,d; while(bfs()) { while(d=dfs(s,INF)) res+=d; } printf("%lld\n",res); } int main() { memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); n=read(),m=read(); for(int i=1;i<=m;i++) { int u=read(),v=read(); LL w=read(); addedge1(u,v,w); addedge1(v,u,w); } s=1,t=2*n; for(int i=1;i<=n;i++) { int x=read(); if(i==1||i==n) { insert(i,i+n,INF); continue; } insert(i,i+n,x); } SPFA(); for(int u=1;u<=n;u++) { for(int i=0;i<G[u].size();i++) { int j=G[u][i]; int v=Edges1[j].to; if(dis[v]==dis[u]+Edges1[j].w) insert(u+n,v,INF); } } Dinic(); return 0; }