• [bzoj1221]软件开发


    记源点为S,汇点为T,第i天裂成两个点,分别是i1和i2,表示剩余的毛巾(都是脏毛巾,因为一定可以做到每天不剩余干净的毛巾)和使用的毛巾(用来保证最大流符合条件),然后考虑以下边:
    1.S向每一个i1连一条(ni,0)的边,表示用过的毛巾;
    2.i2向每一个T连一条(ni,0)的边,表示消耗毛巾;
    3.每一个i1向(i+1)1连一条(inf,0)的边,表示剩余毛巾的传递;
    4.S向每一个i2连一条(ni/inf,F)的边,表示买毛巾;
    5.每一个i1向(i+a+1)2连一条(inf,Fa)的边,表示用a方法洗毛巾;
    6.每一个i1向(i+b+1)2连一条(inf,Fb)的边,表示用b方法洗毛巾。
    这样就可以处理好所有问题,跑最小费用最大流即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 2005
     4 #define oo 0x3f3f3f3f
     5 struct ji{
     6     int nex,to,len,cost;
     7 }edge[N*10];
     8 queue<int>q;
     9 int E,n,a,b,f,fa,fb,t,head[N],from[N],d[N],vis[N];
    10 void add(int x,int y,int z,int w){
    11     edge[E].nex=head[x];
    12     edge[E].to=y;
    13     edge[E].len=z;
    14     edge[E].cost=w;
    15     head[x]=E++;
    16     if (E&1)add(y,x,0,-w);
    17 }
    18 bool spfa(){
    19     memset(vis,0,sizeof(vis));
    20     memset(d,oo,sizeof(d));
    21     d[0]=0;
    22     q.push(0);
    23     while (!q.empty()){
    24         int k=q.front();
    25         q.pop();
    26         vis[k]=0;
    27         for(int i=head[k];i!=-1;i=edge[i].nex){
    28             int v=edge[i].to;
    29             if ((edge[i].len)&&(d[v]>d[k]+edge[i].cost)){
    30                 d[v]=d[k]+edge[i].cost;
    31                 from[v]=i;
    32                 if (!vis[v]){
    33                     vis[v]=1;
    34                     q.push(v);
    35                 }
    36             }
    37         }
    38     }
    39     return d[t]<oo;
    40 }
    41 int dinic(){
    42     int ans=0;
    43     while (spfa()){
    44         int len=oo;
    45         for(int i=t;i;i=edge[from[i]^1].to)len=min(len,edge[from[i]].len);
    46         ans+=len*d[t];
    47         for(int i=t;i;i=edge[from[i]^1].to){
    48             edge[from[i]].len-=len;
    49             edge[from[i]^1].len+=len;
    50         }
    51     }
    52     return ans;
    53 }
    54 int main(){
    55     scanf("%d%d%d%d%d%d",&n,&a,&b,&f,&fa,&fb);
    56     memset(head,-1,sizeof(head));
    57     for(int i=1;i<=n;i++){
    58         scanf("%d",&t);
    59         add(0,i,t,0);
    60         add(0,i+n,t,f);
    61         add(i+n,2*n+1,t,0);
    62         if (i<n)add(i,i+1,oo,0);
    63         if (i+a<n)add(i,i+a+n+1,oo,fa);
    64         if (i+b<n)add(i,i+b+n+1,oo,fb);
    65     }
    66     t=2*n+1; 
    67     printf("%d",dinic());
    68 }
    View Code
  • 相关阅读:
    LeetCode Array Easy 414. Third Maximum Number
    LeetCode Linked List Medium 2. Add Two Numbers
    LeetCode Array Easy 283. Move Zeroes
    LeetCode Array Easy 268. Missing Number
    LeetCode Array Easy 219. Contains Duplicate II
    LeetCode Array Easy 217. Contains Duplicate
    LeetCode Array Easy 189. Rotate Array
    LeetCode Array Easy169. Majority Element
    LeetCode Array Medium 11. Container With Most Water
    LeetCode Array Easy 167. Two Sum II
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11357407.html
Copyright © 2020-2023  润新知