题意:
给定一个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 ",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 ",mincost,v); 151 } 152 } 153 } 154 return 0; 155 }