题目链接:https://ac.nowcoder.com/acm/contest/5666
题目大意:给你一个n,m和m条有向边ai->bi和费用ci。
每次询问u/v。回答把每条边的费用修改为u/v时。从1流一个流量到n的最小费用。如果无法流到输出NaN。其实就是把所以边容量修改为u。从1流v的流量到n的费用/v。
图片说明

思路:对于每次询问我们不能跑一次费用流。因为容量一样。你们我们根据费用流的算法流程。在每次寻找增广路SPAF()时。都会找到流量为1的路。我们统计下每个流量下的费用sum[i]和第i条增广路的费用s1[i]。那么我们在出来询问时。判断最大流*u<v就NaN,否则就选择前u/v条增广路,每条流量为v。和第u/v+1条增广路流量为u%v。

#include<bits/stdc++.h>
#define LL long long
using namespace std;
const LL maxn=305;

LL s1[305], sum[305], tot=0;
struct Mcmf_flow{
    bool vis[maxn];
    LL dis[maxn];
    LL pre[maxn];
    LL last[maxn];
    LL flow[maxn];
    LL zdl, fy;
    //dis最小花费;pre每个点的前驱;last每个点的所连的前一条边;flow源点到此处的流量
    struct Edge {
        LL to,next,flow,dis;//flow流量 dis花费
    } e[maxn];
    LL head[maxn],cut;
    queue <LL> q;

    void init(){
        memset(s1, 0, sizeof(s1));
        memset(sum, 0, sizeof(sum));
        memset(head,-1,sizeof(head));
        tot=0;
        cut=-1;//初始化
        zdl=fy=0;
    }

    void add_e(LL from,LL to,LL flow,LL dis) {
        e[++cut].next=head[from];
        e[cut].to=to;
        e[cut].flow=flow;
        e[cut].dis=dis;
        head[from]=cut;
    }

    void add(LL x, LL y, LL z, LL f){
        add_e(x,y,z,f);
        add_e(y,x,0,-f);
    }

    bool spfa(LL s,LL t) {
        memset(dis,0x7f,sizeof(dis));
        memset(flow,0x7f,sizeof(flow));
        memset(vis,0,sizeof(vis));
        q.push(s);
        vis[s]=1; dis[s]=0; pre[t]=-1;
        while (!q.empty()) {
            LL now=q.front();
            q.pop(); vis[now]=0;
            for (LL i=head[now]; i!=-1; i=e[i].next) {
                if (e[i].flow>0 && dis[e[i].to]>dis[now]+e[i].dis) { //正边
                    dis[e[i].to]=dis[now]+e[i].dis;
                    pre[e[i].to]=now;
                    last[e[i].to]=i;
                    flow[e[i].to]=min(flow[now],e[i].flow);//
                    if (!vis[e[i].to]) {
                        vis[e[i].to]=1;
                        q.push(e[i].to);
                    }
                }
            }
        }
        return pre[t]!=-1;
    }

    void MCMF(LL s, LL t) {
        while (spfa(s,t)) {
            LL now=t;
            zdl+=flow[t];
            fy+=flow[t]*dis[t];
            sum[++tot]=fy;//得到sum[]
            s1[tot]=sum[tot]-sum[tot-1];//得到s1[]

            while (now!=s) {
                //从源点一直回溯到汇点
                e[last[now]].flow-=flow[t];//flow和dis容易搞混
                e[last[now]^1].flow+=flow[t];
                now=pre[now];
            }
        }
    }

}min_Flow;

int main() {
    LL n,m,s,t,x,y,z,f;
    while(~scanf("%lld%lld", &n, &m)){
        min_Flow.init();
        for (LL i=1; i<=m; i++) {
            scanf("%lld%lld%lld",&x,&y,&f);
            min_Flow.add(x,y,1,f);
        }
        s=1, t=n;
        min_Flow.MCMF(s, t);
        LL mx=min_Flow.zdl;
        LL q; scanf("%lld", &q);
        while(q--){

            LL u, v; scanf("%lld%lld", &u, &v);
            LL w=v/u;
            if(mx*u<v){
                printf("NaN\n");
            }
            else{
                LL ans=sum[v/u]*u+s1[w+1]*(v%u);
                LL gcd=__gcd(v, ans);
                printf("%lld/%lld\n", ans/gcd, v/gcd);
            }
        }
    }

    return 0;
}