zoukankan      html  css  js  c++  java
  • [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
    ",MC());
    113     return 0;
    114 } 
  • 相关阅读:
    原型和原型链的理解
    vue2.0 购物车小球的实现
    canvas 实现规则多边形
    ES6全套教程
    利用canvas实现雪花的飘动
    前端 原型对象中this的认识
    JavaScript——创建对象
    javaScript——原型继承四步曲
    AltiumDesigner使用小窍门 (转)
    C指针理解(转)
  • 原文地址:https://www.cnblogs.com/skylee03/p/7259136.html
Copyright © 2011-2022 走看看