zoukankan      html  css  js  c++  java
  • [AHOI2014/JSOI2014]支线剧情 有上下界费用流

    ~~~题面~~~

    题解:

    第一眼费用流,,然后想了好久怎么建图,,,最后发现是最小费用可行流的板子题。。。。

    其实还没有很懂这个算法,所以这里只是摆一下步骤,以后再补理解吧。

    首先一个思路就是转换图,将有上下限的图变为普通的网络流图,然后再跑费用流。

    所以建图其实和有上下界的网络流一样的。。。

    1,首先建立超级源点汇点ss和tt

    2,对于原图中每一条边x ---> y,设其上下界为(l, r),费用为cost,那么连边的时候将流量变为r - l即可

    3,对于任意点i,记d[i]为它的富余流量,即入度的下界和 - 出度的下界和。

      若d[i] > 0,则连边ss ----> i, 流量为d[i] , 费用0

      若d[i] < 0,则连边i ----> tt,流量为-d[i],费用0

    4,连边t ---> s,流量inf,费用0

    答案即为ans + 所有边下界 * 边的费用

    其实可以感性的理解为先有了一个不一定合法的解(下界*费用),然后再利用费用流使用最小的代价使得答案合法。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define R register int
      4 #define AC 400
      5 #define ac 100000
      6 #define inf 2139062143
      7 #define getchar() *o++
      8 char READ[5001000], *o = READ;
      9 int n, ans, s, t1, t;
     10 int last[AC], dis[AC], disflow[AC], d[AC];
     11 int date[ac], Next[ac], haveflow[ac], cost[ac], Head[AC], tot = 1;
     12 bool z[AC];
     13 deque<int> q;
     14 
     15 inline int read()
     16 {
     17     int x=0;char c=getchar();
     18     while(c > '9' || c < '0') c = getchar();
     19     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
     20     return x;
     21 }
     22 
     23 inline void add(int f,int w,int S,int C)
     24 {
     25     date[++tot] = w, Next[tot] = Head[f], haveflow[tot] = S, cost[tot] = C, Head[f] = tot;
     26     date[++tot] = f, Next[tot] = Head[w], cost[tot] = -C, Head[w] = tot;
     27     //printf("%d %d %d %d
    ",f,w,S,C);
     28 }
     29 
     30 void pre()
     31 {
     32     int a,b,c;
     33     n=read();
     34     t1 = n + 1, s = n + 2, t = n + 3;
     35     for(R i=1;i<=n;i++)
     36     {
     37         a=read();
     38         for(R j=1;j<=a;j++)
     39         {
     40             b=read(),c=read();
     41             --d[i], ++d[b];
     42             ans += c;
     43             add(i, b, inf, c);
     44         }
     45     }
     46     for(R i=2;i<=n;i++) 
     47         add(i, t1, inf, 0);
     48     for(R i=1;i<=n;i++)
     49     {
     50         if(d[i] > 0) add(s, i, d[i], 0);
     51         if(d[i] < 0) add(i, t, -d[i], 0);
     52     }    
     53     add(t1, 1, inf, 0);//是费用为0!
     54 }
     55 
     56 inline void aru()
     57 {
     58     int x = t;
     59     while(x != s)
     60     {
     61         haveflow[last[x]] -= disflow[t];
     62         haveflow[last[x] ^ 1] += disflow[t];
     63         x = date[last[x] ^ 1];
     64     }
     65     ans += disflow[t] * dis[t];    
     66 }
     67 
     68 bool spfa()
     69 {
     70     int x, now;
     71     dis[s] = 0, disflow[s] = inf, z[s] = true;
     72     q.push_front(s);
     73     while(!q.empty())
     74     {
     75         x = q.front();
     76         q.pop_front();
     77         z[x] = false;//标记出列
     78         for(R i=Head[x]; i ;i=Next[i])
     79         {
     80             now = date[i];
     81             if(haveflow[i] && dis[now] > dis[x] + cost[i])
     82             {//要有流量啊
     83                 dis[now] = dis[x] + cost[i];
     84                 last[now] = i;
     85                 disflow[now] = min(disflow[x], haveflow[i]);
     86                 if(!z[now])
     87                 {
     88                     z[now] = true;
     89                     if(!q.empty() && dis[now] < q.front()) q.push_front(now);
     90                     else q.push_back(now);
     91                 }
     92             }
     93         }
     94     }
     95     if(dis[t] != inf) aru();
     96     return dis[t] != inf;
     97 }
     98 
     99 bool spfa1()
    100 {
    101     int x,now;
    102     z[s]=true,dis[s]=0,disflow[s]=inf;
    103     q.push_front(s);
    104     while(!q.empty())
    105     {
    106         x=q.front();
    107         q.pop_front();
    108         z[x]=false;
    109         for(int i=Head[x]; i ;i=Next[i])
    110         {
    111             now=date[i];
    112             if(haveflow[i] && dis[now]>dis[x]+cost[i])
    113             {
    114                 dis[now]=dis[x]+cost[i];
    115                 last[now]=i;
    116                 disflow[now]=min(disflow[x],haveflow[i]);//以点为单位记录到这个点时的流量
    117                 if(!z[now]) 
    118                 {
    119                     z[now] = true;
    120                     q.push_front(now);
    121                 }
    122                 /*if(!z[now] && now!=t)
    123                 {
    124                     if(!q.empty() && dis[now]<dis[q.front()])    q.push_front(now);
    125                     else q.push_back(now);
    126                     z[now]=true;
    127                 }*/
    128             }
    129         }
    130     }
    131     //更新路径
    132     if(dis[t] != inf) aru();
    133     return dis[t] != inf;
    134 }
    135 
    136 void work()
    137 {
    138     //printf("%d
    ",ans);
    139     memset(dis, 127, sizeof(dis));
    140     while(spfa())
    141         memset(dis, 127, sizeof(dis));
    142     printf("%d
    ",ans);
    143 }
    144 
    145 int main()
    146 {
    147 //    freopen("in.in","r",stdin);
    148     fread(READ, 1, 5000000, stdin);
    149     pre();
    150     work();
    151 //    fclose(stdin);
    152     return 0;
    153 }
  • 相关阅读:
    互联网改变的产业 汽车 x 互联网 = 汽车革命
    我有一个实现HMI触摸屏的资源【4418开发平台】降d成本
    iTOP-4412开发板裸机开发环境文档分享
    2019年最受欢迎iTOP-4418开发板_新产品研发必备利器
    安卓触控一体机为什么得到大家认可?远比Windows系统一体机大受欢迎
    新手入门嵌入式学习单片机?stm32?树莓派?4412开发板资料大汇报-基础了解
    iTOP-4418开发板-Qt系统下运行摄像头测试程序
    iTOP-4418/6818开发板-QtE4.7WIFI_MT6620热点
    iTOP-4412开发板-使用PartitionManager分区之后tf卡无法识别
    迅为iTOP-4418/6818开发板-MiniLinux-GPS使用文档
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9176006.html
Copyright © 2011-2022 走看看