zoukankan      html  css  js  c++  java
  • [NOI2008]志愿者招募

    OJ题号:
    BZOJ1061

    题目大意:
    有$n$个任务,$m$个志愿者,完成每个任务$i$至少需要$a_i$个人,每个人只有在$s_i$到$t_i$的时候有空,并需要被支付$c_i$的报酬,求完成所有任务的最小支出。

    思路:
    “先挖空后补空”。
    将每个时间抽象成点,并在时间轴的两端增加源汇$S$和$T$,每个相邻的时间点连一条边,容量为$inf-a_i$,费用为$0$。
    对于每个人,连一条从$s_i$到$t_i+1$的容量为$inf$的边,费用为$c_i$。跑最小费用最大流即可。
    第一遍的增广其实是没用的,因为费用是$0$,它的作用是把最早建的边中因为$inf$产生多余的容量去掉。
    后面的几次增广就相当于补空。

    Rank1和Rank2为什么跑这么快?

     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 const int V=1002,E=22002;
    15 int s,t;
    16 struct Edge {
    17     int from,to,remain,cost;
    18 };
    19 Edge e[E];
    20 int sz;
    21 std::vector<int> g[V];
    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 a[V],p[V],d[V];
    28 bool inq[V];
    29 inline int Augment() {
    30     memset(a,0,sizeof a);
    31     a[s]=inf;
    32     std::fill(&d[1],&d[t+1],inf);
    33     d[s]=0;
    34     memset(inq,0,sizeof inq);
    35     std::queue<int> q;
    36     q.push(s);
    37     inq[s]=true;
    38     while(!q.empty()) {
    39         int x=q.front();
    40         q.pop();
    41         inq[x]=false;
    42         for(unsigned i=0;i<g[x].size();i++) {
    43             Edge &y=e[g[x][i]];
    44             if(y.remain&&(d[x]+y.cost<d[y.to])) {
    45                 d[y.to]=d[x]+y.cost;
    46                 a[y.to]=std::min(a[x],y.remain);
    47                 p[y.to]=g[x][i];
    48                 if(!inq[y.to]) {
    49                     q.push(y.to);
    50                     inq[y.to]=true;
    51                 }
    52             }
    53         }
    54     }
    55     return a[t];
    56 }
    57 inline int EdmondsKarp() {
    58     int mincost=0;
    59     while(int flow=Augment()) {
    60         for(int i=t;i!=s;i=e[p[i]].from) {
    61             e[p[i]].remain-=flow;
    62             e[p[i]^1].remain+=flow;
    63         }
    64         mincost+=d[t]*flow;
    65     }
    66     return mincost;
    67 }
    68 int main() {
    69     int n=getint(),m=getint();
    70     s=0,t=n+1;
    71     add_edge(s,1,inf,0);
    72     add_edge(1,s,0,0);
    73     for(int i=1;i<=n;i++) {
    74         add_edge(i,i+1,inf-getint(),0);
    75         add_edge(i+1,i,0,0);
    76     }
    77     for(int i=1;i<=m;i++) {
    78         int s=getint(),t=getint(),c=getint();
    79         add_edge(s,t+1,inf,c);
    80         add_edge(t+1,s,0,-c);
    81     }
    82     printf("%d
    ",EdmondsKarp());
    83     return 0;
    84 } 

  • 相关阅读:
    Google maps not working IE11
    谷歌地图插件
    杨辉三角python的最佳实现方式,牛的不能再牛了
    今日头条推荐算法原理全文详解
    项目启动大会要点
    学金融应该看的书籍
    【从0到1】经典语录
    appium学习链接记录
    Axure-计算输入字数
    如何提升个人专业能力
  • 原文地址:https://www.cnblogs.com/skylee03/p/7464592.html
Copyright © 2011-2022 走看看