[ZJOI2010]网络扩容

Posted skylee的OI博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[ZJOI2010]网络扩容相关的知识,希望对你有一定的参考价值。

OJ题号:

BZOJ1834、洛谷2604

思路:

对于第一问,直接跑一遍最大流即可。
对于第二问,将每条边分成两种情况,即将每条边拆成两个:
不需扩容,即残量大于零时,相当于这条边费用为$0$;
需要扩容,即残量等于零时,可以扩容很多次,将残量设为$inf$或者$k$(实际上最多扩容$k$次)。
由于$k≤10$,跑$k$遍流量为$1$的最小费用流即可。

  1 #include<queue>
  2 #include<cstdio>
  3 #include<cctype>
  4 #include<vector>
  5 #include<cstring>
  6 inline int getint() {
  7     char ch;
  8     while(!isdigit(ch=getchar()));
  9     int x=ch^0;
 10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^0);
 11     return x;
 12 }
 13 const int inf=0x7fffffff;
 14 int n,m,k,s,t;
 15 struct Edge {
 16     int from,to,remain,cost;
 17 };
 18 const int E=20000,V=1001;
 19 Edge e[E];
 20 std::vector<int> g[V];
 21 int sz=0;
 22 inline void add_edge(const int u,const int v,const int w,const int c) {
 23     e[sz]=(Edge){u,v,w,c};
 24     g[u].push_back(sz);
 25     sz++;
 26 }
 27 int p[V],a[V];
 28 inline int MFAugment() {
 29     memset(a,0,sizeof a);
 30     a[s]=inf;
 31     std::queue<int> q;
 32     q.push(s);
 33     while(!q.empty()&&!a[t]) {
 34         int x=q.front();
 35         q.pop();
 36         for(unsigned i=0;i<g[x].size();i++) {
 37             Edge &y=e[g[x][i]];
 38             if(!a[y.to]&&y.remain) {
 39                 p[y.to]=g[x][i];
 40                 a[y.to]=std::min(a[x],y.remain);
 41                 q.push(y.to);
 42             }
 43         }
 44     }
 45     return a[t];
 46 }
 47 inline int MF() {
 48     int maxflow=0;
 49     while(int flow=MFAugment()) {
 50         for(int i=t;i!=s;i=e[p[i]].from) {
 51             e[p[i]].remain-=flow;
 52             e[p[i]^1].remain+=flow;
 53         }
 54         maxflow+=flow;
 55     }
 56     return maxflow;
 57 }
 58 int d[V];
 59 bool inq[V];
 60 inline int MCAugment() {
 61     d[s]=0;
 62     for(int i=2;i<=t;i++) d[i]=inf;
 63     std::queue<int> q;
 64     q.push(s);
 65     memset(inq,0,sizeof inq);
 66     inq[s]=true;
 67     while(!q.empty()) {
 68         int x=q.front();
 69         q.pop();
 70         inq[x]=false;
 71         for(unsigned i=0;i<g[x].size();i++) {
 72             Edge &y=e[g[x][i]];
 73             if((d[x]+y.cost<d[y.to])&&y.remain&&(y.cost>=0)) {
 74                 d[y.to]=d[x]+y.cost;
 75                 p[y.to]=g[x][i];
 76                 if(!inq[y.to]) {
 77                     q.push(y.to);
 78                     inq[y.to]=true;
 79                 }
 80             }
 81         }
 82     }
 83     return d[t];
 84 }
 85 inline int MC() {
 86     int mincost=0;
 87     while(k--) {
 88         int cost=MCAugment();
 89         for(int i=t;i!=s;i=e[p[i]].from) {
 90             e[p[i]].remain--;
 91             e[p[i]^1].remain++;
 92         }
 93         mincost+=cost;
 94     }
 95     return mincost;
 96 }
 97 int main() {
 98     n=getint(),m=getint(),k=getint();
 99     s=1,t=n;
100     while(m--) {
101         int u=getint(),v=getint(),w=getint(),c=getint();
102         add_edge(u,v,w,c);
103         add_edge(v,u,0,-c);
104     }
105     printf("%d ",MF());
106     int oldsz=sz;
107     for(int i=0;i<oldsz;i++) {
108         int u=e[i].from,v=e[i].to,w=e[i].remain,c=e[i].cost;
109         e[i]=(Edge){u,v,w,0};
110         add_edge(u,v,inf,c);
111     }
112     printf("%d\n",MC());
113     return 0;
114 } 

 

以上是关于[ZJOI2010]网络扩容的主要内容,如果未能解决你的问题,请参考以下文章

[zjoi2010]网络扩容

[ZJOI2010]网络扩容

[ZJOI2010]网络扩容

BZOJ1834 [ZJOI2010] network 网络扩容

bzoj1834 ZJOI2010网络扩容(费用流)

bzoj:1834: [ZJOI2010]network 网络扩容