Description
给定一个流网络 (n le 50, m le 100, sum m le 10^4),(q (sum q le 10^6)) 次询问,每次给定一个分数 (u/v),问所有边的容量是 (u/v) 时费用流的费用。
Solution
很自然想到把每次增广的费用都记下来,对于每个询问贪心处理即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 105;
namespace flow {
const int N = 205;
const int M = 405;
const int inf = 1e+12;
struct Edge {
int p, c, w, nxt = -1;
} e[N];
int s, t, tans, ans, cost, ind, bus[N], qhead = 0, qtail = -1, qu[M],vis[N], dist[N];
void graph_link(int p, int q, int c, int w) {
e[ind].p = q;
e[ind].c = c;
e[ind].w = w;
e[ind].nxt = bus[p];
bus[p] = ind;
++ind;
}
void make(int p, int q, int c, int w) {
graph_link(p, q, c, w);
graph_link(q, p, 0, -w);
}
int dinic_spfa() {
qhead = 0;
qtail = -1;
memset(vis, 0x00, sizeof vis);
memset(dist, 0x3f, sizeof dist);
vis[s] = 1;
dist[s] = 0;
qu[++qtail] = s;
while (qtail >= qhead) {
int p = qu[qhead++];
vis[p] = 0;
for (int i = bus[p]; i != -1; i = e[i].nxt)
if (dist[e[i].p] > dist[p] + e[i].w && e[i].c > 0) {
dist[e[i].p] = dist[p] + e[i].w;
if (vis[e[i].p] == 0)
vis[e[i].p] = 1, qu[++qtail] = e[i].p;
}
}
return dist[t] < inf;
}
int dinic_dfs(int p, int lim) {
if (p == t)
return lim;
vis[p] = 1;
int ret = 0;
for (int i = bus[p]; i != -1; i = e[i].nxt) {
int q = e[i].p;
if (e[i].c > 0 && dist[q] == dist[p] + e[i].w && vis[q] == 0) {
int res = dinic_dfs(q, min(lim, e[i].c));
cost += res * e[i].w;
e[i].c -= res;
e[i ^ 1].c += res;
ret += res;
lim -= res;
if (lim == 0)
break;
}
}
return ret;
}
vector<int> solve(int _s,int _t) {
s=_s; t=_t;
vector <int> vec;
int oldcost=0;
cost=0;
ans=0;
while (dinic_spfa()) {
memset(vis, 0x00, sizeof vis);
ans += dinic_dfs(s, inf);
vec.push_back(cost-oldcost);
oldcost=cost;
}
return vec;
}
void init() {
memset(bus, 0xff, sizeof bus);
ind=0;
}
}
int n,m,q,t1,t2,t3;
void solve()
{
flow::init();
for(int i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&t1,&t2,&t3);
flow::make(t1,t2,1,t3);
}
vector<int> vec = flow::solve(1,n);
vector<int> sum = vec;
for(int i=1;i<sum.size();i++) sum[i]+=sum[i-1];
scanf("%lld",&q);
for(int i=1;i<=q;i++)
{
int u,v; //u/v
scanf("%lld%lld",&u,&v);
int g;
if(flow::ans * u < v)
{
puts("NaN");
continue;
}
int _v=v;
int a0=1;
int ans=0;
int pos=v/u;
v-=pos*u;
if(pos) ans+=sum[pos-1]*u;
ans+=vec[pos]*v;
a0*=_v;
g=__gcd(a0,ans);
if(g) a0/=g, ans/=g;
printf("%lld/%lld
",ans,a0);
}
}
signed main()
{
ios::sync_with_stdio(false);
while(~scanf("%lld%lld",&n,&m))
{
solve();
}
}