https://ac.nowcoder.com/acm/contest/5666/H
把每次询问记作cost(u/v,1)就是每条边容量都是u/v,总流量是1的情况
然后这题的关键就是一个神奇的转换,所有的询问都可以转换成cost(1,v/u)
那么如果是边的容量都为1的话,就巨好求了,每次找一条增广路,流量一定是1的,那么把增广路的个数从小到大记过来(本身就是这样)
假设至多有tot条增广路,那么v<=u*tot,否则就是nan
那么对于d=v/u,t=v%u,d条一定取最小的d条,然后t这个多出来的流量去a[d+1]这条增广路,代价也按比例算一算就好了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxl=210;
const int inf=2e9+10;
int n,m,tot,cnt;
ll ans1,ans2;
int ehead[maxl],dis[maxl],frm[maxl];
ll a[maxl],sum[maxl];
struct ed
{
int frm,to,nxt,w,c;
}e[maxl<<1];
queue<int> q;
bool in[maxl];
inline void add(int u,int v,int w,int c)
{
e[++cnt].to=v;e[cnt].frm=u;
e[cnt].w=w;e[cnt].c=c;
e[cnt].nxt=ehead[u];ehead[u]=cnt;
}
inline void prework()
{
for(int i=1;i<=n;i++)
ehead[i]=0;
int u,v,c;cnt=1;
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&c);
add(u,v,1,c);add(v,u,0,-c);
}
}
inline int spfa()
{
while(!q.empty()) q.pop();
for(int i=1;i<=n;i++)
dis[i]=inf;
q.push(1);dis[1]=0;in[1]=true;
int u,v;
while(!q.empty())
{
u=q.front();q.pop();in[u]=false;
for(int i=ehead[u];i;i=e[i].nxt)
if(e[i].w)
{
v=e[i].to;
if(dis[v]>dis[u]+e[i].c)
{
dis[v]=dis[u]+e[i].c;
frm[v]=i;
if(!in[v])
{
q.push(v);
in[v]=true;
}
}
}
}
return dis[n]<inf;
}
inline void mcf()
{
int i=n,x=inf;
i=frm[n];
while(i>1)
{
x=min(x,e[i].w);
i=frm[e[i].frm];
}
i=frm[n];
while(i>1)
{
e[i].w-=x;
e[i^1].w+=x;
i=frm[e[i].frm];
}
a[++tot]=dis[n];sum[tot]=sum[tot-1]+dis[n];
}
void mainwork()
{
ans1=0;tot=0;
while(spfa())
mcf();
}
inline void print()
{
int _,u,v;scanf("%d",&_);
while(_--)
{
scanf("%d%d",&u,&v);
if(u==0)
{
puts("NaN");
continue;
}
int d=v/u,t=v%u;
if(d>tot || (d==tot && t>0))
{
puts("NaN");
continue;
}
ans1=u*sum[d]+t*a[d+1];
ans2=v;
ll g=__gcd(ans1,ans2);
ans1/=g;ans2/=g;
printf("%lld/%lld\n",ans1,ans2);
}
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
prework();
mainwork();
print();
}
return 0;
}