zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第一场)H.Minimum-cost Flow

    题目链接

    题解思路:其实思路很简单,跑一遍费用流后记录每一条增广路的流量和花费,队这些增广路按照花费排序,之后对每次询问只需要去枚举这些增广路即可,把每条(1,x/y)的边看作是(y,x)的边,最后再对答案除y,这样就有效避免了分数出现的尴尬情况。


    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> PII;
    #define ls l,mid,rt<<1
    #define rs mid+1,r,rt<<1|1
    #define endl '
    '
    #define p4 puts("444")
    const int N = 50+10,M = 1e2+10;
    const double EPS = 1e-12;
    const ll mod = 1e9+7;
    
    int n,m,s,t,q,cnt,maxflow,tot;
    int head[N],cur[N],inq[N],pre[N],path[N];
    ll dis[N],cost;
    
    struct edge{
        int to,next,cap;
        ll cost;
    }E[M<<1];
    struct node{
        void Add(int u,int v,int w,ll c){
            E[cnt].to=v;
            E[cnt].cap=w;
            E[cnt].next=head[u];
            E[cnt].cost=c;
            head[u]=cnt++;
        }
        bool Spfa(){
            for(int i=1;i<=n;i++)cur[i]=head[i],dis[i]=1e18,inq[i]=0,pre[i]=0;
            queue<int>que;
            que.push(s);
            inq[s]=1;
            dis[s]=0;
            while(!que.empty()){
                int u=que.front();que.pop();
                inq[u]=0;
                for(int i=head[u];~i;i=E[i].next){
                    int v=E[i].to;
                    if(E[i].cap&&dis[v]>dis[u]+E[i].cost){
                        pre[v]=i;
                        dis[v]=dis[u]+E[i].cost;
                        if(!inq[v]){
                            inq[v]=1;
                            que.push(v);
                        }
                    }
                }
            }
            return dis[t]==1e18 ? 0 : 1;
        }
        void Solve(){
            while(Spfa()){
                int flow=1e9;
                for(int i=t;i!=s;i=E[pre[i]^1].to)flow=min(flow,E[pre[i]].cap);
                maxflow+=flow;
                path[++tot]=0;
                for(int i=t;i!=s;i=E[pre[i]^1].to){
                    E[pre[i]].cap-=flow;
                    E[pre[i]^1].cap+=flow;
                    cost+=flow*E[pre[i]].cost;
                    path[tot]+=E[pre[i]].cost;
                }
            }
        }
        void Init(){
            maxflow=cost=cnt=tot=0;
            memset(head,-1,sizeof(head));
        }
    }EK;
    
    int main()
    {
        while(~scanf("%d %d",&n,&m)){
            EK.Init();
            int a,b; ll c;
            for(int i=1;i<=m;i++){
                scanf("%d %d %lld",&a,&b,&c);
                EK.Add(a,b,1,c);
                EK.Add(b,a,0,-c);
            }
            ll x,y;
            s=1,t=n;
            EK.Solve();
            scanf("%d",&q);
            while(q--){
                int flag=0;
                ll nowflow=0,nowcost=0;
                scanf("%lld %lld",&x,&y);
                for(int i=1;i<=tot;i++){
                    if(x*(tot-i+1)<y-nowflow){
                        flag=1;
                        break;
                    }
                    int need=min(x,y-nowflow);
                    nowflow+=need;
                    nowcost+=path[i]*need;
                }
                if(flag)puts("NaN");
                else cout<<nowcost/__gcd(nowcost,y)<<"/"<<y/__gcd(nowcost,y)<<endl;
            }
        }
    }
  • 相关阅读:
    char和QChar(Unicode的编码与内存里的值还不是一回事)
    ddd
    vim实用笔记
    设计思想
    await使用中的阻塞和并发
    单元测试
    C#简单实现贪吃蛇程序(LinQ + Entity)
    JS逗号、冒号与括号
    C#实现对文件目录的实时监控
    在线预览PDF
  • 原文地址:https://www.cnblogs.com/Mmasker/p/13293443.html
Copyright © 2011-2022 走看看