zoukankan      html  css  js  c++  java
  • [BZOJ1834][ZJOI2010]network 网络扩容 最大流+费用流

    1834: [ZJOI2010]network 网络扩容

    Time Limit: 3 Sec  Memory Limit: 64 MB Submit: 3330  Solved: 1739 [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
     
     对于第一问,我们直接跑网络流。
    对于第二问,我们先建一个超级源,从这个超级源向1连一条容量为k,费用为0的边。
    之后对于原图的每一条边,建一条容量无限的边,跑最小费用最大流即可。
      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #define maxm 5005
      8 #define maxn 1005
      9 using namespace std;
     10 struct data {
     11     int from,to,next,w,c;
     12 }e[maxm*4];
     13 int head[maxn],cnt;
     14 void add(int u,int v,int w,int c){e[cnt].from=u;e[cnt].next=head[u];e[cnt].to=v;e[cnt].w=w;e[cnt].c=c;head[u]=cnt++;}
     15 int n,m,k;
     16 int q[maxn];
     17 bool vis[maxn];
     18 int dis[maxn];
     19 bool bfs() {
     20     memset(dis,-1,sizeof(dis));
     21     int h=0,t=1;
     22     q[h]=1;
     23     vis[1]=1;
     24     dis[1]=0;
     25     while(h!=t) {
     26         int now=q[h];h++;vis[now]=0;if(h==1000) h=0;
     27         for(int i=head[now];i>=0;i=e[i].next) {
     28             int to=e[i].to;
     29             if(e[i].w&&dis[to]<0) {
     30                 dis[to]=dis[now]+1;
     31                 if(!vis[to]){
     32                     vis[to]=1;
     33                     q[t++]=to;if(t==1000)t=0;
     34                 }
     35             }
     36         }
     37     }
     38     return dis[n]!=-1;
     39 }
     40 int dfs(int now,int a) {
     41     if(now==n||a==0) return a;
     42     int flow=0,f;
     43     for(int i=head[now];i>=0;i=e[i].next) {
     44         int to=e[i].to;
     45         if(dis[to]==dis[now]+1&&e[i].w>0) {
     46             f=dfs(to,min(a,e[i].w));
     47             e[i].w-=f;
     48             e[i^1].w+=f;
     49             flow+=f;
     50             a-=f;
     51             if(a==0) return flow;
     52         }
     53     }
     54     if(!flow) dis[now]=-1;
     55     return flow;
     56 }
     57 void work1() {
     58     int ans=0;
     59     while(bfs()){ans+=dfs(1,2147483647);}
     60     printf("%d ",ans);
     61 }
     62 int cost=0;
     63 bool spfa() {
     64     for(int i=0;i<=n;i++) dis[i]=-1000000000; 
     65     int h=0,t=1;
     66     q[h]=n;
     67     vis[n]=1;
     68     dis[n]=0;
     69     while(h!=t) {
     70         int now=q[h];h++;vis[now]=0;if(h==1000) h=0;
     71         for(int i=head[now];i>=0;i=e[i].next) {
     72             int to=e[i].to;
     73             if(e[i^1].w&&dis[to]<dis[now]+e[i].c) {
     74                 dis[to]=dis[now]+e[i].c;
     75                 if(!vis[to]){
     76                     vis[to]=1;
     77                     q[t++]=to;if(t==1000)t=0;
     78                 }
     79             }
     80         }
     81     }
     82     cost-=dis[0];
     83     return dis[0]!=-1000000000;
     84 }
     85 int ans2;
     86 int zkw(int now,int a) {
     87     if(now==n||a==0){ans2+=cost*a;return a;}
     88     int flow=0,f;vis[now]=1;
     89     for(int i=head[now];i>=0;i=e[i].next) {
     90         int to=e[i].to;
     91         if(dis[to]==dis[now]+e[i].c&&e[i].w>0&&!vis[to]&&(f=zkw(to,min(a,e[i].w)))) {
     92             e[i].w-=f;
     93             e[i^1].w+=f;
     94             flow+=f;
     95             a-=f;
     96             if(a==0) break;
     97         }
     98     }
     99     return flow;
    100 }
    101 void build() {
    102     int t=cnt;
    103     for(int i=0;i<t;i+=2) {
    104         add(e[i].from,e[i].to,1147483647,e[i].c);
    105          add(e[i].to,e[i].from,0,-e[i].c);
    106     }
    107     add(0,1,k,0);
    108     add(1,0,0,0);
    109     for(int i=0;i<t;i++) e[i].c=0;
    110 }
    111 void work2() {
    112     ans2=0;cost=0;
    113     build();
    114     memset(vis,0,sizeof(vis));
    115     while(spfa()) {
    116         do {
    117             memset(vis,0,sizeof(vis));
    118         }while(zkw(0,2147483647));
    119         memset(vis,0,sizeof(vis));cost=0;
    120     }
    121     printf("%d",ans2);
    122 }
    123 int main() {
    124     memset(head,-1,sizeof(head));
    125     scanf("%d%d%d",&n,&m,&k);
    126     for(int i=1;i<=m;i++) {
    127         int u,v,w,c;
    128         scanf("%d%d%d%d",&u,&v,&w,&c);
    129         add(u,v,w,c);add(v,u,0,-c);
    130     }
    131     work1();
    132     work2();
    133 }
    View Code
    O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~
  • 相关阅读:
    水晶报表基础操作技巧收藏
    注册表里相应的
    .Net 中的反射(动态创建类型实例) Part.4动态创建对象
    .Net 中的反射(查看基本类型信息) Part.2
    Javascript多级菜单
    诡异的中毒现象
    js魔力代码
    Silverlight入门教程
    Silverlight 2.0中文学习资源集萃
    jatoolsPrinter 2手册
  • 原文地址:https://www.cnblogs.com/wls001/p/7678966.html
Copyright © 2011-2022 走看看