1. 程式人生 > >2018.10.10【CQOI2015】【BZOJ3931】【洛谷P3171】網路吞吐量(最短路)(最大流)

2018.10.10【CQOI2015】【BZOJ3931】【洛谷P3171】網路吞吐量(最短路)(最大流)

洛谷傳送門

解析:

好粗暴的最短路加最大流。。。

思路:

首先題目要求資料沿最短路傳遞,而且題目都說了DijkstraDijkstra,怎麼還有人寫SPFASPFA,不怕被卡嗎?

於是,我們先DijkstraDijkstra求出最短路。

然後根據題目要求構建流網路圖,就是隻有在最短路樹裡面的邊才能夠加入流網路,並且容量設為INFINF。因為題目說了每條路徑的容量不限。

然後又是經典套路,點有容量怎麼辦?拆點啊,中間連點容量大小的邊。 直接最大流完事。

程式碼:

#include<bits/stdc++.h>
using namespace
std; #define ll long long #define re register #define gc getchar #define pc putchar #define cs const inline int getint(){ re int num; re char c; while(!isdigit(c=gc()));num=c^48; while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48); return num; } cs int N=1003,M=101005; cs int S=0,T=1002; cs ll INF=
0x3f3f3f3f3f3f3f3f; int last[N],nxt[M<<1],to[M<<1],ecnt=1; ll cap[M<<1]; inline void addedge(int u,int v,ll val){ nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,cap[ecnt]=val; nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,cap[ecnt]=0; } int lev[N],cur[N]; inline bool BFS(){ memset(lev,
-1,sizeof lev); queue<int> q; q.push(S),lev[S]=0,cur[S]=last[S]; while(!q.empty()){ int u=q.front(); q.pop(); for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){ if(cap[e]&&lev[v]==-1){ lev[v]=lev[u]+1; if(v==T)return true; cur[v]=last[v]; q.push(v); } } } return false; } inline ll Dinic(cs int &u,cs ll &flow){ if(u==T)return flow; ll ans=0; for(int &e=cur[u],v=to[e];e;v=to[e=nxt[e]]){ if(cap[e]&&lev[v]>lev[u]){ ll delta=Dinic(v,min(flow-ans,cap[e])); if(delta){ cap[e]-=delta; cap[e^1]+=delta; ans+=delta; if(ans==flow)return ans; } } } return ans; } inline ll maxflow(){ ll ans=0; while(BFS())ans+=Dinic(S,INF); return ans; } int c[N]; namespace SP{//Shortest_Path int last[N],nxt[M<<1],to[M<<1],ecnt; ll w[M<<1]; inline void Addedge(int u,int v,ll val){ nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val; nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,w[ecnt]=val; } ll dist[N]; bitset<N> vis; inline void dijkstra(){ priority_queue<pair<ll,int>,vector<pair<ll,int> > ,greater<pair<ll,int> > > q; vis.reset(); memset(dist,0x3f,sizeof dist); q.push(make_pair(dist[1]=0,1)); while(!q.empty()){ int u=q.top().second; q.pop(); if(vis[u])continue; vis[u]=true; for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]) if(dist[v]>dist[u]+w[e])q.push(make_pair(dist[v]=dist[u]+w[e],v)); } } } using SP::Addedge; using SP::dist; int n,m; signed main(){ n=getint(),m=getint(); for(int re i=1;i<=m;++i){ int u=getint(),v=getint(),d=getint(); Addedge(u,v,d); } SP::dijkstra(); for(int re u=1;u<=n;++u) for(int re e=SP::last[u],v=SP::to[e];e;v=SP::to[e=SP::nxt[e]]){ if(dist[v]==dist[u]+SP::w[e])addedge(u+500,v,INF); } for(int re i=1;i<=n;++i){ int val=getint(); addedge(i,i+500,val); } addedge(S,1+500,INF); addedge(n,T,INF); cout<<maxflow(); return 0; }