BZOJ3931 CQOI2015 网络吞吐量
3931: [CQOI2015]网络吞吐量
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2083 Solved: 870
[Submit][Status][Discuss]
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
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
Source
先跑出最短路,然后依据条件建图即可,最后跑出最大流即可
#include <bits/stdc++.h> #define ll long long #define inf 1000000000007 using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=2e5+10; struct node{ int x,y,next; ll v; }e[MAXN<<1]; int linkk[MAXN<<1],len=0,n,m,dis[MAXN],vis[MAXN],a[MAXN],b[MAXN],d[MAXN],qq[MAXN],head,tail,level[2000]; typedef pair <int,int> pii; priority_queue < pii,vector<pii>,greater<pii> > q; inline void insert(int xx,int yy,ll vv){ e[++len].y=yy;e[len].v=vv;e[len].next=linkk[xx];linkk[xx]=len; } void dijsktra(){ memset(dis,127,sizeof(dis)); q.push(make_pair(0,1)); dis[1]=0; while(!q.empty()){ int tn=q.top().second;q.pop(); if(vis[tn]) continue; vis[tn]=1; for(int i=linkk[tn];i;i=e[i].next){ if(dis[tn]+e[i].v<dis[e[i].y]){ dis[e[i].y]=dis[tn]+e[i].v; q.push(make_pair(dis[e[i].y],e[i].y)); } } } } namespace zhangenming{ inline bool getlevel(){ memset(level,-1,sizeof(level)); head=tail=0; qq[++tail]=1;level[1]=0; while(head<tail){ int tn=qq[++head]; for(int i=linkk[tn];i;i=e[i].next){ if(level[e[i].y]==-1&&e[i].v){ level[e[i].y]=level[tn]+1; qq[++tail]=e[i].y; } } } return level[2*n]!=-1; } inline ll getmaxflow(int st,ll flow){ if(st==2*n) return flow; ll d,maxflow=0; for(int i=linkk[st];i&&maxflow<flow;i=e[i].next){ if(level[e[i].y]==level[st]+1&&e[i].v>0){ d=getmaxflow(e[i].y,min(e[i].v,flow-maxflow)); e[i].v-=d; if(i%2==0) e[i-1].v+=d; else e[i+1].v+=d; maxflow+=d; } } if(!maxflow) level[st]=-1; return maxflow; } int dinic(){ ll ans=0;ll sum; while(getlevel()){ sum=getmaxflow(1,inf); ans+=sum; } cout<<ans<<endl; } void init(){ n=read();m=read(); for(int i=1;i<=m;i++){ a[i]=read();b[i]=read();d[i]=read(); insert(a[i],b[i],d[i]); insert(b[i],a[i],d[i]); } dijsktra(); len=0; memset(linkk,0,sizeof(linkk)); for(int i=1;i<=m;i++){ if(dis[a[i]]+d[i]==dis[b[i]]) insert(a[i]+n,b[i],inf),insert(b[i],a[i]+n,0); if(dis[b[i]]+d[i]==dis[a[i]]) insert(b[i]+n,a[i],inf),insert(a[i],b[i]+n,0); } for(int i=1;i<=n;i++){ int vv=read(); if(i!=1&&i!=n) insert(i,i+n,vv); else insert(i,i+n,inf); insert(i+n,i,0); } dinic(); } } int main(){ using namespace zhangenming; init(); return 0; }