• bzoj 1061 [Noi2008]志愿者招募


    无源汇上下界最小费用可行流。

    每天作为一个点。

    每一天向下一天连一条上界为正无穷下界为该天所需人数费用为0的边。

    对于每个志愿者,从他结束工作的后一天向开始工作的第一天连一条上界为正无穷下界为0费用为招募费的边。

    在这个无源汇网络中,招募一个志愿者即产生一个Ti+1—>Si—>Si+1—>Si+2—>……—>Ti—>Ti+1的圈,使Si到Ti天的流量加1。

    原图跑无源汇上下界最小费用可行流就行了。

    类比poj3680,对于一个条件覆盖连续点问题,通常用将点依次相连再加边的方式,两题区别在于有上界正向连边最大流,有下界反向连边可行流。

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<queue>
     6 using namespace std;
     7 const int dian=1005;
     8 const int bian=30005;
     9 const int INF=0x3f3f3f3f;
    10 int h[dian],nxt[bian],ver[bian],val[bian],cos[bian];
    11 int d[dian],v[dian],minn[dian],with[dian],in[dian],out[dian];
    12 int n,m,tot,aa,bb,cc,mf;
    13 int S,T;
    14 void add(int a,int b,int c,int d,int e){
    15     tot++;ver[tot]=b;val[tot]=d-c;cos[tot]=e;nxt[tot]=h[a];h[a]=tot;
    16     tot++;ver[tot]=a;val[tot]=0;cos[tot]=-e;nxt[tot]=h[b];h[b]=tot;
    17     in[b]+=c;out[a]+=c;mf+=c*e;
    18 }
    19 bool tell(){
    20     memset(v,0,sizeof(v));
    21     memset(d,0x3f,sizeof(d));
    22     memset(with,0,sizeof(with));
    23     memset(minn,0x3f,sizeof(minn));
    24     queue<int>q;
    25     q.push(S);
    26     v[S]=1;
    27     d[S]=0;
    28     while(!q.empty()){
    29         int x=q.front();
    30         q.pop();
    31         v[x]=0;
    32         for(int i=h[x];i;i=nxt[i]){
    33             int y=ver[i];
    34             if(d[y]>d[x]+cos[i]&&val[i]){
    35                 d[y]=d[x]+cos[i];
    36                 minn[y]=min(minn[x],val[i]);
    37                 with[y]=i;
    38                 if(!v[y]){
    39                     v[y]=1;
    40                     q.push(y);
    41                 }
    42             }
    43         }
    44     }
    45     if(d[T]==0x3f3f3f3f)
    46         return false;
    47     return true;
    48 }
    49 int zeng(){
    50     for(int i=T;i!=S;i=ver[with[i]^1]){
    51         val[with[i]]-=minn[T];
    52         val[with[i]^1]+=minn[T];
    53     }
    54     return d[T]*minn[T];
    55 }
    56 int dinic_cost(){
    57     int r=0;
    58     while(tell())
    59         r+=zeng();
    60     return r;
    61 }
    62 int main(){
    63     memset(h,0,sizeof(h));
    64     memset(nxt,0,sizeof(nxt));
    65     memset(in,0,sizeof(in));
    66     memset(out,0,sizeof(out));
    67     tot=1,mf=0;
    68     scanf("%d%d",&n,&m);
    69     S=n+2,T=n+3;
    70     for(int i=1;i<=n;i++){
    71         scanf("%d",&aa);
    72         add(i,i+1,aa,INF,0);
    73     }
    74     for(int i=1;i<=m;i++){
    75         scanf("%d%d%d",&aa,&bb,&cc);
    76         add(bb+1,aa,0,INF,cc);
    77     }
    78     for(int i=1;i<=n+1;i++){
    79         if(in[i]>out[i])
    80             add(S,i,0,in[i]-out[i],0);
    81         else if(out[i]>in[i])
    82             add(i,T,0,out[i]-in[i],0);
    83     }
    84     printf("%d",mf+dinic_cost());
    85     return 0;
    86 }
  • 相关阅读:
    绿色版QQ2010SP3手记
    使用DQL语句查询数据
    Oracle 数据库密码过期问题
    redis语法与命令
    Redis安装与启动
    centos 7下搭建Redis5.x版集群
    MySQL 命令行操作教程
    Redis集群分片原理及选举流程
    截取文件名与后缀名
    Java POI读取excel 支持xls、xlsx
  • 原文地址:https://www.cnblogs.com/dugudashen/p/6272332.html
Copyright © 2020-2023  润新知