• 牛客多校1——Minimum-cost Flow


    题意:

      给定一个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 }
  • 相关阅读:
    方法的重载
    this用法
    简单的随机数 代码和笔记
    java内存简单剖析
    day 28
    day 27
    day 26
    day 25
    day 24
    day 23
  • 原文地址:https://www.cnblogs.com/orangeko/p/13338392.html
Copyright © 2020-2023  润新知