zoukankan      html  css  js  c++  java
  • [上下界费用流]JZOJ 3302 供电网络

    Description

    阿狸和桃子居住的世界里, 只有一个国家, 这个国家有很多城市, 每个城市直接由中央政府管辖.
    电力是这个国家的唯一能源, 但是每个城市的发电能力都不一样, 于是就产生了某些城市电力不足, 而某些城市却电力过剩的情况.
    阿狸作为国家的首席工程师, 阿狸的一项重要工作就是均衡整个国家的电力, 使得每个城市的电力都恰好没有剩余或不足.
    好在一些城市之间有电线可以输送电力, 这些电线都有自己的输送上限和下限, 并且输送电力的同时会产生大量的热.
    每条电线i 发出的热量一定是关于输送电量的一个没有常数项的二次函数,即a_i*x^2+b_i*x, 并且由于电线是二极管做成的, 很显然只能单向输送电力. 每单位热量需要用1 单位的金币来冷却. 任何两个城市之间, 至多有一条电线.
    不幸的是, 有时电力网络不像我们想的那么完美, 某些情况下可能无论如何都不能满足整个国家的电力需求. 这种情况下就只好向别的世界购买电力或者将电力输出给别的世界(注意, 每个城市的电力不能有剩余!), 每个城市买入或者输出电力的价格是不一样的(输出也要花钱).
    由于阿狸的国家没有小数的概念, 输送,、购买或者交换电力都必须是以整数1 为单位.
    阿狸的任务是最小化金币的花费(买入/送出的费用+电线上发热的冷却费用),他最近被这个问题搞得焦头烂额, 以至于没有时间去陪桃子玩, 结果天天被桃子骂T_T. 好在有你, 万能的程序猿, 请你编写一个程序来帮阿狸解决这个问题吧.
     

    Input

    第一行2 个整数, n 和m, 分别是城市个数和有向电线条数.
    接下来n 行, 每行3 个整数[left, in, out], 其中第k 行表示第k 个城市的信息:
    left 表示这个城市剩余(负数为不足)的电量, -5 <= left <= 5.
    in, out 表示这个城市买入或送出一个单位电量的价格. 0 <= in, out <= 10000
    最后m 行, 每行6 个整数, u, v, a, b, L, U 其中第k 行表示第k 条电线的信息:
    u, v 分别表示电线的开始和结束城市(电力只能从u 输送到v).
    a, b 表示电线发热的二次函数的二次项和一次项.
    L, U 表示电线输送电力的下界和上界.

    Output

    仅一个整数, 表示最小的金币花费.
     

    Sample Input

    3 2
    1 1 1
    -2 20 0
    -4 20 0
    1 2 1 0 0 10
    2 3 0 3 0 10

    Sample Output

    53
    样例解释:
    城市1买入5个单位电力, 花费5.
    城市1输出6个单位电力到城市2, 花费36.
    城市3输出4个单位电力到城市3, 花费12.
    总花费53.
     
     

    Data Constraint

    对于5%的数据满足m = 0.
    对于30%的数据满足n <= 30, L = 0, a = 0.
    对于60%的数据满足n <= 50, m <= 200.
    对于100%的数据满足n <= 200, m <= 600, u != v, 1 <= u, v <= n, 1 <= a, b <=3, 1 <= L <= 10, 1 <= L <= U <= 100, 0 <= in, out <= 100, -5 <= left <= 5.

    分析

    题面已经很明显地告诉这是个网络流了,而且显然是上下界费用流

    我们从s往所有为正数的点连一条费用0上下界都为ai的边,从所有为负数的点向t连一条费用0上下界为-ai的边

    表示这个点一开始有这么多的电或需要输出这么多的电

    然后每个点向t连无限流量,费用为输出的边,从s向每个点连无限流量,费用为输入的边

    然后对于电线的消耗,这是个二次函数,所以要拆开写

    权值就会变为a+b,3*a+b,5*a+b,7*a+b……

    先把下界的代价加进去,然后为了防止TLE,我们采用动态加边的方法

    上下界网络流戳这个大爷

    #include <iostream> 
    #include <cstdio>
    #include <queue>
    #include <memory.h>
    using namespace std;
    const int N=2e2+10;
    const int M=6e2+10;
    const int Inf=2147483647;
    struct Edge {
        int u,v,l,r,a,b;
    }e[M];
    struct Graph {
        int v,c,w,nx;
    }g[10000010];
    int cnt=1,list[N],dis[N],vis[N],a[N],I[N][N],f[N];
    int s,t,ss,tt;
    int n,m,ans;
    
    void Add_Edge(int u,int v,int c,int w) {
        g[++cnt]=(Graph){v,c,w,list[u]};list[u]=cnt;
        g[++cnt]=(Graph){u,0,-w,list[v]};list[v]=cnt;
    }
    
    void Add_Pipe(int u,int v,int l,int r,int w) {
        Add_Edge(u,v,r-l,w);
        if (l) a[u]-=l,a[v]+=l,ans+=w*l;
    }
    
    bool SPFA() {
        queue<int> q;
        while (!q.empty()) q.pop();
        memset(dis,0x7f,sizeof dis);memset(vis,0,sizeof vis);
        q.push(ss);vis[ss]=1;dis[ss]=0;
        for (int i=1;i<=m;i++)
            if (I[e[i].u][e[i].v]==e[i].l&&e[i].l<e[i].r) {
                e[i].l++;
                Add_Edge(e[i].u,e[i].v,1,(2*e[i].l-1)*e[i].a+e[i].b);
            }
        while (!q.empty()) {
            int u=q.front();q.pop();
            for (int i=list[u];i;i=g[i].nx)
                if (g[i].c&&dis[g[i].v]>dis[u]+g[i].w) {
                    dis[g[i].v]=dis[u]+g[i].w;f[g[i].v]=i;
                    if (!vis[g[i].v]) q.push(g[i].v);
                    vis[g[i].v]=1;
                }
            vis[u]=0;
        }
        return dis[tt]!=0x7f7f7f7f;
    }
    
    void MCF() {
        int x=tt;
        while (f[x]) {
            ans+=g[f[x]].w;
            I[g[f[x]^1].v][g[f[x]].v]++;I[g[f[x]].v][g[f[x]^1].v]--;
            g[f[x]].c--;g[f[x]^1].c++;
            x=g[f[x]^1].v;
        }
    }
    
    void Dinic() {
        while (SPFA())
            MCF();
    }
    
    int main() {
        scanf("%d%d",&n,&m);
        s=0;t=n+1;ss=n+2;tt=n+3;
        Add_Pipe(t,s,0,Inf,0);
        for (int i=1;i<=n;i++) {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            if (a>0) Add_Pipe(s,i,a,a,0); else Add_Pipe(i,t,-a,-a,0);
            Add_Pipe(s,i,0,Inf,b);Add_Pipe(i,t,0,Inf,c);
        }
        for (int i=1;i<=m;i++) {
            scanf("%d%d%d%d%d%d",&e[i].u,&e[i].v,&e[i].a,&e[i].b,&e[i].l,&e[i].r);
            Add_Pipe(e[i].u,e[i].v,e[i].l,e[i].l,0);
            ans+=e[i].a*e[i].l*e[i].l+e[i].b*e[i].l;
            I[e[i].u][e[i].v]+=e[i].l;I[e[i].v][e[i].u]-=e[i].l;
        }
        for (int i=s;i<=t;i++) if (a[i]<0) Add_Pipe(i,tt,0,-a[i],0); else Add_Pipe(ss,i,0,a[i],0);
        Dinic();
        printf("%d",ans);
    }
    View Code
    在日渐沉没的世界里,我发现了你。
  • 相关阅读:
    记录两种获取配置文件的方法
    jsp-自定义标签
    转载 -jsp静态包含和动态包含的区别
    Linux基础知识笔记
    关于HTTP协议
    关于orcale创建type的一些小经验(遇到的坑)
    servlet处理乱码之post和get
    发布restful类型的接口
    ros2 dashing 安装失败指南
    exit回调
  • 原文地址:https://www.cnblogs.com/mastervan/p/11145008.html
Copyright © 2011-2022 走看看