zoukankan      html  css  js  c++  java
  • [BZOJ 1834] [ZJOI2010]network 网络扩容

    1834: [ZJOI2010]network 网络扩容

    Time Limit: 3 Sec
    Memory Limit: 64 MB

    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

    Day1

    【题解】

    网络流啊TAT 每次都是数组开小啊

    这道题第一问就是直接dinic最大流

    第二问就是在做费用流的时候求出的解是满足最大流情况下的解。设第一问的最大流是ANS,要扩容K,有可能在加了新边后最大流大于ANS+K。这样费用可能不是最小的。因此我们可以在1号或N号点新增一条边,容量是K,费用是0。这样就限制了最大流。

      1 #include <stdio.h>
      2 #include <queue>
      3 #include <string.h>
      4 using namespace std;
      5 const int B=30010;
      6 const int INF=2139062143;
      7 int next[B], head[B], to[B], flow[B], w[B], c[B], oq[B];
      8 int pre[B], cnt=-1, bi[B], n, m, k, ans=0, d[B];
      9 bool vis[B];
     10 int u[B], v[B], _f[B], _w[B];
     11 queue <int> q;
     12 inline void add(int u,int v,int flo,int _w) {
     13     cnt++; to[cnt]=v; next[cnt]=head[u];    head[u]=cnt; flow[cnt]=flo; w[cnt]=_w;
     14 }
     15 inline int min(int a,int b) {return a<b?a:b;}
     16 inline void G(int &x) {
     17     int y=0, yy=1; char ch=getchar();
     18     while(ch<'0'||ch>'9') {
     19         if(ch=='-') yy=-1;
     20         ch=getchar();
     21     }
     22     while(ch>='0'&&ch<='9') {
     23         y=(y<<1)+(y<<3)+ch-'0';
     24         ch=getchar();
     25     }
     26     x=y*yy;
     27 }
     28 inline void qclear() {
     29     while(!q.empty()) q.pop();
     30 }
     31 inline bool getdfn() {
     32     qclear();
     33     memset(c,-1,sizeof(c));
     34     q.push(1); c[1]=1;
     35     while(!q.empty()) {
     36         int top=q.front();
     37         q.pop();
     38         for (int i=head[top];i>=0;i=next[i]) {
     39             int t=to[i];
     40             if(c[t]>=0||flow[i]==0) continue;
     41             c[t]=c[top]+1;
     42             q.push(t);
     43             if(t==n) return 1;
     44         } 
     45     }
     46     return 0;
     47 }
     48 int dinic(int x,int low) {
     49     if(x==n) return low;
     50     int flo,r=low;
     51     for (int i=head[x];i>=0;i=next[i]) {
     52         int t=to[i], fl=flow[i];
     53         if(c[t]!=c[x]+1 || fl==0) continue;
     54         flo=dinic(t,min(r,fl));
     55         r-=flo;
     56         flow[i]-=flo;
     57         flow[i^1]+=flo;
     58         if(!r) return low;
     59     }
     60     if(r==low) c[x]=-1;
     61     return low-r;
     62 }
     63 inline bool spfa() {
     64     memset(vis,0,sizeof(vis));
     65     memset(oq,0,sizeof(oq));
     66     memset(d,0X7f,sizeof(d));
     67     qclear();
     68     vis[1]=1; d[1]=0; q.push(1);
     69     while(!q.empty()) {
     70         int top=q.front(); q.pop();
     71         vis[top]=0; oq[top]++;
     72         if(oq[top]>n) return 0;
     73         for (int i=head[top];i>=0;i=next[i]) {
     74             if(flow[i]&&d[top]+w[i]<d[to[i]]) {
     75                 d[to[i]]=d[top]+w[i];
     76                 pre[to[i]]=i;
     77                 if(!vis[to[i]]) {
     78                     vis[to[i]]=1;
     79                     q.push(to[i]);
     80                 }
     81             }
     82         }
     83     }
     84     if(d[n]==INF) return 0;
     85     return 1;
     86 }
     87 inline void mincostflow() {
     88     int s=INF;
     89     for (int i=pre[n];i>=0;i=pre[to[i^1]]) {
     90         s=min(s,flow[i]);
     91         if(to[i^1]==1) break;
     92     }
     93     for (int i=pre[n];i>=0;i=pre[to[i^1]]) {
     94         flow[i]-=s;
     95         flow[i^1]+=s;
     96         ans+=s*w[i];
     97         if(to[i^1]==1) break;
     98     }
     99 }
    100 int main() {
    101     G(n), G(m), G(k);
    102     memset(head,-1,sizeof(head));
    103     for (int i=1;i<=m;++i) {
    104         G(u[i]), G(v[i]), G(_f[i]), G(_w[i]);
    105         add(u[i],v[i],_f[i],0);
    106         add(v[i],u[i],0,0);
    107     }
    108     int _flowx=0;
    109     while(getdfn()) _flowx += dinic(1,INF);
    110     printf("%d ",_flowx);
    111     for (int i=1;i<=m;++i) {
    112         add(u[i],v[i],INF,_w[i]);
    113         add(v[i],u[i],0,-_w[i]);
    114     }
    115     add(n,n+1,k,0); add(n+1,n,0,0);
    116     ++n;
    117     while(spfa()) mincostflow();
    118     printf("%d
    ",ans);
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    不足百行代码 实体数组转DataTable通用类
    【翻译】WEB安全设计规范(4.1)
    也为读者说几句(兼为什么要骂烂书译者)
    重用之前应仔细分析问题用错轮子有感
    最长代码有多长:不符[单一职责原则(SRP)]的常见设计
    "千里之堤毁于蚁穴"重点项目不能交付之谜(一)泥淖中的验收测试
    企业快速开发框架基于配置文件
    从面试题看高级软件工程师需要哪些技艺
    面试英语【转】
    测试
  • 原文地址:https://www.cnblogs.com/TonyNeal/p/bzoj1834.html
Copyright © 2011-2022 走看看