bzoj 3931 [CQOI2015]网络吞吐量(最短路,最大流)

【题目链接】

    http://www.lydsy.com/JudgeOnline/problem.php?id=3931

【题意】

    只能通过1-n的最短路,求网络最大流

【思路】

    分别以1,n为起点做最短路,则可以判断一条边是否在最短路上。

    以最短路构建网络,并且将一个点拆成两个中间连c[i]表示结点容量限制。

【代码】

  1 #include<set>
  2 #include<cmath>
  3 #include<queue>
  4 #include<vector>
  5 #include<cstdio>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<algorithm>
  9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
 11 using namespace std;
 12 
 13 typedef long long ll;
 14 const int N = 2e3+10;
 15 const int M = 4e5+10;
 16 const int inf = 1e9;
 17 const ll llinf = 1e18;
 18 
 19 ll read() {
 20     char c=getchar();
 21     ll f=1,x=0;
 22     while(!isdigit(c)) {
 23         if(c=='-') f=-1; c=getchar();
 24     }
 25     while(isdigit(c))
 26         x=x*10+c-'0',c=getchar();
 27     return x*f;
 28 }
 29 
 30 struct DEdge {
 31     int u,v; ll cap,flow;
 32 };
 33 struct Dinic {
 34     int n,m,s,t;
 35     int d[N],cur[N],vis[N];
 36     vector<int> g[N];
 37     vector<DEdge> es;
 38     queue<int> q;
 39     void init(int n) {
 40         this->n=n;
 41         es.clear();
 42         FOR(i,0,n) g[i].clear();
 43     }
 44     void clear() {
 45         FOR(i,0,(int)es.size()-1) es[i].flow=0;
 46     }
 47     void AddEdge(int u,int v,ll w) {
 48         es.push_back((DEdge){u,v,w,0});
 49         es.push_back((DEdge){v,u,0,0});
 50         m=es.size();
 51         g[u].push_back(m-2);
 52         g[v].push_back(m-1);
 53     }
 54     int bfs() {
 55         memset(vis,0,sizeof(vis));
 56         q.push(s); d[s]=0; vis[s]=1;
 57         while(!q.empty()) {
 58             int u=q.front(); q.pop();
 59             FOR(i,0,(int)g[u].size()-1) {
 60                 DEdge& e=es[g[u][i]];
 61                 int v=e.v;
 62                 if(!vis[v]&&e.cap>e.flow) {
 63                     vis[v]=1;
 64                     d[v]=d[u]+1;
 65                     q.push(v);
 66                 }
 67             }
 68         }
 69         return vis[t];
 70     }
 71     ll dfs(int u,ll a) {
 72         if(u==t||!a) return a;
 73         ll flow=0,f;
 74         for(int& i=cur[u];i<g[u].size();i++) {
 75             DEdge& e=es[g[u][i]];
 76             int v=e.v;
 77             if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow)))>0) {
 78                 e.flow+=f; 
 79                 es[g[u][i]^1].flow-=f;
 80                 flow+=f; a-=f;
 81                 if(!a) break;
 82             }
 83         }
 84         return flow;
 85     }
 86     ll MaxFlow(int s,int t) {
 87         this->s=s,this->t=t;
 88         ll flow=0;
 89         while(bfs()) {
 90             memset(cur,0,sizeof(cur));
 91             flow+=dfs(s,llinf);
 92         }
 93         return flow;
 94     }
 95 } dc;
 96 
 97 struct Edge {
 98     int u,v;ll w; int nxt;
 99 }e[M];
100 int en=1,front[N];
101 void adde(int u,int v,ll w) 
102 {
103     e[++en]=(Edge){u,v,w,front[u]}; front[u]=en;
104 }
105 
106 int n,m;
107 ll c[N],dis1[N],dis2[N];
108 
109 int inq[N]; queue<int> q;
110 void spfa(int s,ll* dis)
111 {
112     memset(inq,0,sizeof(inq));
113     FOR(i,0,n) dis[i]=llinf;
114     q.push(s); inq[s]=1; dis[s]=0;
115     while(!q.empty()) {
116         int u=q.front(); q.pop();
117         inq[u]=0;
118         trav(u,i) {
119             int v=e[i].v;
120             if(dis[v]>dis[u]+(ll)e[i].w) {
121                 dis[v]=dis[u]+(ll)e[i].w;
122                 if(!inq[v]) {
123                     inq[v]=1; q.push(v);
124                 }
125             }
126         }
127     }
128 }
129 
130 int main()
131 {
132     n=read(),m=read();
133     FOR(i,1,m) {
134         int u=read(),v=read(); ll w=read();
135         adde(u,v,w),adde(v,u,w);
136     }
137     dc.init(n*2+2);
138     spfa(1,dis1),spfa(n,dis2);
139     ll dist=dis1[n];
140     FOR(i,1,n)
141         c[i]=read(),dc.AddEdge(i,i+n,c[i]);
142     for(int i=2;i<=en;i+=2) {
143         int u=e[i].u,v=e[i].v;
144         if(dis1[u]>dis1[v]) swap(u,v);
145         if((ll)dis1[u]+e[i].w+dis2[v]==dist)
146             dc.AddEdge(u+n,v,inf),dc.AddEdge(v+n,u,inf);
147     }
148     printf("%lld
",dc.MaxFlow(n+1,n));
149     return 0;
150 }

P.S. spfa写错还浑然不知,省选药丸的节奏QWQ

原文地址:https://www.cnblogs.com/lidaxin/p/5310495.html