zoukankan      html  css  js  c++  java
  • BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)

    第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然  后跑最小费用最大流就OK了.

    ------------------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<queue>
     
    #define rep(i,n) for(int i=0;i<n;++i)
    #define clr(x,c) memset(x,c,sizeof(x))
    #define Rep(i,l,r) for(int i=l;i<r;++i)
     
    using namespace std;
     
    const int maxn=1005,maxm=5005;
    const int inf=0x7fffffff;
     
    vector<int> g[maxn];
    int d[maxn];
    int cur[maxn];
    int num[maxn];
    int p[maxn];
    int a[maxn];
    int inq[maxn];
    int u[maxm],v[maxm],c[maxm];
    int n,m,s,t,k;
     
    struct Edge {
    int from,to,cap,flow,cost;
    Edge(int u,int v,int c,int f,int w):
    from(u),to(v),cap(c),flow(f),cost(w) {}
    };
     
    vector<Edge> edges;
     
    void addEdge(int u,int v,int cap,int cost) {
    edges.push_back( (Edge) {u,v,cap,0,cost} );
    edges.push_back( (Edge) {v,u,0,0,-cost} );
    int M=edges.size();
    g[u].push_back(M-2);
    g[v].push_back(M-1);
    }
     
    int augment() {
    int a=inf,x=t;
    while(x!=s) {
    Edge &e=edges[p[x]];
    a=min(a,e.cap-e.flow);
    x=e.from;
    }
    x=t;
    while(x!=s) {
    Edge &e=edges[p[x]];
    e.flow+=a;
    edges[p[x]^1].flow-=a;
    x=e.from;
    }
    return a;
    }
     
    int maxFlow() {
    int flow=0;
    clr(d,0); clr(cur,0); clr(num,0);
    num[0]=n;
    int x=s;
    while(d[s]<n) {
    if(x==t) {
    flow+=augment();
    x=s;
    }
    int ok=0;
    Rep(i,cur[x],g[x].size()) {
    Edge &e=edges[g[x][i]];
    if(e.cap>e.flow && d[e.to]+1==d[x]) {
    ok=1;
    cur[x]=i;
    p[e.to]=g[x][i];
    x=e.to;
    break;
    }
    }
    if(!ok) {
    int M=n-1;
    rep(i,g[x].size()) {
    Edge &e=edges[g[x][i]];
    if(e.cap>e.flow) M=min(M,d[e.to]);
    }
    if(--num[d[x]]==0) break;
    num[d[x]=M+1]++;
    cur[x]=0;
    if(x!=s) x=edges[p[x]].from;
    }
    }
    return flow;
    }
     
    bool spfa(int &flow,int &cost) {
    rep(i,n) d[i]=inf;
    clr(inq,0);
    d[s]=0; inq[s]=1; p[s]=0; a[s]=inf;
    queue<int> q;
    q.push(s);
    while(!q.empty()) {
    int x=q.front(); q.pop();
    inq[x]=0;
    rep(i,g[x].size()) {
    Edge &e=edges[g[x][i]];
    if(e.cap>e.flow && d[e.to]>d[x]+e.cost) {
    d[e.to]=d[x]+e.cost;
    p[e.to]=g[x][i];
    a[e.to]=min(a[x],e.cap-e.flow);
    if(!inq[e.to]) {
    q.push(e.to);
    inq[e.to]=1;
    }
    }
    }
    }
    if(d[t]==inf) return 0;
    flow+=a[t];
    cost+=d[t]*a[t];
    int x=t;
    while(x!=s) {
    Edge &e=edges[p[x]];
    e.flow+=a[t];
    edges[p[x]^1].flow-=a[t];
    x=e.from;
    }
    return 1;
    }
     
    int minCost() {
    int flow=0,cost=0;
    while(spfa(flow,cost));
    return cost;
    }
     
    void init() {
    rep(i,n+2) g[i].clear();
    edges.clear();
    }
     
    int main()
    {
    freopen("test.in","r",stdin);
    freopen("test.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    init();
    rep(i,m) {
    int cap;
    scanf("%d%d%d%d",&u[i],&v[i],&cap,&c[i]);
    addEdge(--u[i],--v[i],cap,0);
    }
    s=0; t=n-1; printf("%d ",maxFlow());
    rep(i,m) addEdge(u[i],v[i],k,c[i]);
    addEdge(n,0,k,0); addEdge(n-1,n+1,k,0);
    n+=2;
    s=n-2; t=n-1; printf("%d ",minCost());
    return 0;
    }

      

    ------------------------------------------------------------------------------------ 

    1834: [ZJOI2010]network 网络扩容

    Time Limit: 3 Sec  Memory Limit: 64 MB
    Submit: 1854  Solved: 919
    [Submit][Status][Discuss]

    Description

    给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

    Input

    输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

    Output

    输出文件一行包含两个整数,分别表示问题1和问题2的答案。

    Sample Input

    5 8 2
    1 2 5 8
    2 5 9 9
    5 1 6 2
    5 1 1 8
    1 2 8 7
    2 5 4 9
    1 2 1 1
    1 4 2 1

    Sample Output

    13 19
    30%的数据中,N<=100
    100%的数据中,N<=1000,M<=5000,K<=10

    HINT

    Source

  • 相关阅读:
    简单的BMCP位图图片压缩算法
    163相册验证码图片的识别手记之二 识别
    认父亲的DbParameter!!
    文件同步精灵(初版)
    163相册验证码图片的识别手记之一 去除干扰
    C#中WebService里的回车符"\r"丢失问题
    PHP 杂谈《重构改善既有代码的设计》之二 对象之间搬移特性
    PHP5计划任务离线功能的原理
    (转)程序员疫苗:代码注入
    window7环境,不安装Oracle,使用PL/SQL Developer结合oracle精简客户端,管理Oracle数据库
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/4375412.html
Copyright © 2011-2022 走看看