牛客多校1——Minimum-cost Flow

题意:

  给定一个n点m边的带费用的网络和q次询问,每次询问会对该网络的每条边的容量进行再定义,求每次改完边的容量后,图中流通一单位流量所需要的最小花费是多少。

 

做法:

  因为n和m的大小,无法跑多次的MCMF,所以考虑先把整个网络边容积设成1,跑一次MCMF,在MCMF的过程中记录一下,跑到第i条增广路时的花费为多少。此举相当于,在边容积为1的网络上发送一单位的流量时,花费为多少。

  之后,对于每次修改边容积成 u/v,可以看做是在边的容积为u的网络上,发送v流量所消耗的mincost。

  此举意味着,之前所记录的每条增广路的花费cost[i]*u,即可得到每发送v流量所需要的mincost。

  也就是说,共所需 v/u 组流量为u的增广路,加上 v%u 组流量为1的增广路

  显然此时网络的最大流为原网络的最大流*u,如果maxflow < v,说明无解

  有解情况下的mincost = 前v/u组增广路的mincost * u + v % u组流量为1的mincost

  对于mincost/v约分,即可得到最终答案

 

CODE

 

  1 #include <bits/stdc++.h>
  2 #define dbg(x) cout << #x << " = " << x << endl
  3 #define eps 1e-8
  4 #define pi acos(-1.0)
  5 
  6 using namespace std;
  7 typedef long long LL;
  8 const int maxn =  1e3 +7;
  9 const int inf  =  0x3f3f3f3f;
 10 
 11 template<class T>inline void read(T &res)
 12 {
 13     char c;T flag = 1;
 14     while((c = getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
 15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
 16 }
 17 
 18 LL n,m,s,t,cnt;
 19 LL mincost;
 20 LL head[maxn], dis[maxn], vis[maxn], cur[maxn];
 21 LL sum[maxn << 1];
 22 
 23 vector<LL>path;
 24 
 25 struct edge {
 26     LL to, next, cap, cost;
 27 }e[maxn << 1];
 28 
 29 void add(LL x,LL y,LL z,LL c) {
 30     e[cnt].to = y;
 31     e[cnt].cap = z;
 32     e[cnt].cost = c;
 33     e[cnt].next = head[x];
 34     head[x] = cnt++;
 35 }
 36 
 37 void BuildGraph(LL x,LL y,LL z,LL c) {
 38     add(x,y,z,c);
 39     add(y,x,0,-c);
 40 }
 41 
 42 bool spfa()
 43 {
 44     //cout << '!' << endl;
 45     queue<int>q;
 46     for(LL i=1;i<=n;i++)
 47         dis[i] = inf;
 48     memset(vis,0,sizeof(vis));
 49     dis[s] = 0;
 50     vis[s] = 1;
 51     q.push(s);
 52     while(!q.empty())
 53     {
 54         //cout << '?' << endl;
 55         LL u = q.front();
 56         q.pop();
 57         vis[u] = 0;
 58         for(LL i = head[u]; i != -1; i = e[i].next) {
 59             LL v = e[i].to;
 60            // dbg(u);dbg(v);
 61             if(e[i].cap>0 && dis[u]+e[i].cost < dis[v]) {
 62                 dis[v] = dis[u]+e[i].cost;
 63                 if(!vis[v]) {
 64                     vis[v] = 1;
 65                     q.push(v);
 66                 }
 67             }
 68         }
 69     }
 70     if(dis[t] != inf)
 71         return 1;
 72     return 0;
 73 }
 74 
 75 LL dfs(LL u,LL flow) {
 76     vis[u] = 1;
 77     if(u == t)
 78         return flow;
 79     for(LL& i = cur[u];i != -1;i = e[i].next) {
 80         LL v = e[i].to;
 81         if(e[i].cap>0&&dis[v] == dis[u]+e[i].cost&&!vis[v])
 82         {
 83             LL di = dfs(v, min(flow, e[i].cap));
 84             if(di>0) {
 85                 e[i].cap -= di;
 86                 e[i^1].cap += di;
 87                 mincost += di*e[i].cost;
 88                 return di;
 89             }
 90         }
 91     }
 92     vis[u] = 0;
 93     return 0;
 94 }
 95 
 96 LL dinic() {
 97     LL maxflow = 0;
 98     path.clear();
 99     while(spfa()) {
100         //cout << '!' << endl;
101         path.push_back(dis[t]);
102         memcpy(cur,head,sizeof(head));
103         while(LL d = dfs(s,inf))
104             maxflow += d;
105     }
106     return maxflow;
107 }
108 
109 int main() {
110     while(cin >> n >> m) {
111         cnt = 0;
112         s = 1, t = n;
113         mincost = 0;
114         memset(head, -1, sizeof(head));
115         for ( int i  =  1; i <=  m; ++i ) {
116             int a, b;
117             int c;
118             read(a); read(b);
119             read(c);
120             BuildGraph(a, b, 1, c);
121         }
122         dinic();
123         int pathnum  =  path.size();
124         //dbg(pathnum);
125         for ( int i = 0; i <= pathnum - 1; ++i ) {
126             sum[i + 1] = sum[i] + path[i];
127         }
128         int q;
129         read(q);
130         while(q--) {
131             LL u, v, maxflow;
132             read(u); read(v);
133             maxflow = u * pathnum;
134             //dbg(u);dbg(maxflow);
135             // for ( int i   =   1; i <  =   cnt; ++i ) {
136             //     printf("w: e[%d]:%lf\n",i,e[i].w);
137             // }
138             
139             //dbg(a);dbg(b);
140             // dbg(maxflow);
141             // dbg(mincost);
142             if(maxflow < v) {
143                 puts("NaN");
144             }
145             else {
146                 int a = v / u, b = v - u * a;
147                 mincost = sum[a] * u + path[a] * b;
148                 LL temp = __gcd(mincost, v);
149                 mincost /= temp, v /= temp;
150                 printf("%lld/%lld\n",mincost,v);
151             }
152         }
153     }
154     return 0;
155 }

 

posted @ 2020-07-19 01:23  Orangeko  阅读(246)  评论(0)    收藏  举报