Evanyou Blog 彩带

网络流二十四题之餐巾计划问题

  题目传送门

  这题的思路我觉得five20巨佬讲的已经非常清晰了,所以就推荐一下他的题解,我就只放代码了

//It is made by HolseLee on 7th Feb 2018
//Luogu.org P1251
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<queue>
#include<algorithm>
using namespace std;
#define inf 1e12
const int N=20001;
typedef long long ll;
ll n,d1,d2,c1,c2,p;
ll sta,endd,head[N];
ll cnt=1,ans,dis[N];
bool vis[N],inq[N];
struct Node{
  ll to,val;
  ll cost,next;
}edge[N<<2];
queue<ll>team;
inline ll read()
{
  char ch=getchar();ll num=0;bool flag=false;
  while(ch<'0'||ch>'9'){if(ch=='-')flag=true;ch=getchar();}
  while(ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
  return flag?-num:num;
}
inline void add(ll x,ll y,ll z,ll c)
{
  edge[++cnt].to=y;
  edge[cnt].val=z;
  edge[cnt].cost=c;
  edge[cnt].next=head[x];
  head[x]=cnt;
}
inline void add_edge(ll x,ll y,ll z,ll c)
{add(x,y,z,c);add(y,x,0,-c);}
inline bool spfa()
{
  for(ll i=sta;i<=endd;i++)dis[i]=inf;
  memset(inq,false,sizeof(inq));
  team.push(endd);dis[endd]=0;
  inq[endd]=true;
  while(!team.empty()){
    ll u=team.front();team.pop();
    inq[u]=false;
    for(ll i=head[u];i!=-1;i=edge[i].next){
      ll v=edge[i].to;
      if(edge[i^1].val&&dis[v]>dis[u]-edge[i].cost){
    dis[v]=dis[u]-edge[i].cost;
    if(!inq[v]){
      inq[v]=true;
      team.push(v);
    }
      }
    }
  }
  return dis[sta]<inf;
}
inline ll dfs(ll u,ll nowflow)
{
  vis[u]=true;
  if(nowflow==0||u==endd)return nowflow;
  ll used=0;
  for(ll i=head[u];i!=-1;i=edge[i].next){
    ll v=edge[i].to;
    if(!vis[v]&&edge[i].val&&dis[v]==dis[u]-edge[i].cost){
      ll ka=dfs(v,min(nowflow,edge[i].val));
      edge[i].val-=ka;edge[i^1].val+=ka;
      used+=ka;nowflow-=ka;
      if(nowflow==0)return used;
    }
  }
  return used;
}
void ready()
{
  memset(head,-1,sizeof(head));
  n=read();ll x;
  sta=0;endd=2*n+1;
  for(ll i=1;i<=n;i++){
    x=read();
    add_edge(sta,i+n,x,0);
    add_edge(i,endd,x,0);}
  p=read();
  d1=read();c1=read();
  d2=read();c2=read();
  for(ll i=1;i<=n;i++){
    add_edge(sta,i,inf,p);
    if(i+d1<=n)add_edge(i+n,i+d1,inf,c1);
    if(i+d2<=n)add_edge(i+n,i+d2,inf,c2);
    if(i+1<=n)add_edge(i,i+1,inf,0);
  }
}
void work()
{
  while(spfa()){
    vis[endd]=true;
    while(vis[endd]){
      memset(vis,false,sizeof(vis));
      ll ka=dfs(sta,inf);
      ans+=ka*dis[sta];
    }
  }
  printf("%lld",ans);
}
int main()
{
  ready();
  work();
  return 0;
}

 

posted @ 2018-02-07 16:55  HolseLee  阅读(205)  评论(0编辑  收藏  举报