看到那么多大佬都开坑刷题,那我也随波逐流一下。。。虽然保不准什么时候就弃掉了。。

  进度:

8/24


 

  1、餐巾计划问题(费用流)

  题目传送门:https://www.luogu.org/problemnew/show/P1251

  这道题还是比较思维的。。。(然而说白了都是套路)

  显然我们可以把餐巾使用量看作网络的流量,把花费看作网络的费用。

  这道题主要的难点就在于如何保证每天一定有ai条餐巾用,以及处理干净餐巾的来源与脏餐巾的去向。因为只能通过源汇来控制整个网络的流量(即餐巾的使用量),所以我们可以把使用一条干净餐巾的过程拆成两个部分:(1)把一条干净的餐巾流进汇点;(2)让一条脏餐巾从源点流出。

  于是把一天拆成两个点,一个用来接受脏餐巾,一个用来使用干净的餐巾,然后按题意连边(把脏餐巾洗干净),跑最小费用最大流就行了。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#define ll long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define eps 1e-18
inline ll read()
{
    ll tmp=0; char c=getchar(),f=1;
    for(;c<'0'||'9'<c;c=getchar())if(c=='-')f=-1;
    for(;'0'<=c&&c<='9';c=getchar())tmp=(tmp<<3)+(tmp<<1)+c-'0';
    return tmp*f;
}
using namespace std;
struct edge{
    int from,to,nxt;
    ll w,flow;
}e[1600010];
int fir[4010],inq[4010],last[4010];
ll dist[4010];
int q[1600010];
int a[2010];
int n,S,T,tot=0;
void add(int x,int y,ll w,ll f)
{
    e[tot].from=x; e[tot].to=y; e[tot].w=w; e[tot].flow=f; e[tot].nxt=fir[x]; fir[x]=tot++;
    e[tot].from=y; e[tot].to=x; e[tot].w=-w; e[tot].flow=0; e[tot].nxt=fir[y]; fir[y]=tot++;
}
int spfa()
{
    int h=1,t=1,i;
    for(i=0;i<=T;i++)dist[i]=inf,inq[i]=0,last[i]=-1;
    q[1]=S; dist[S]=0; inq[S]=1;
    while(h<=t){
        int now=q[h++]; inq[now]=0;
        for(i=fir[now];~i;i=e[i].nxt)
            if(e[i].flow&&dist[e[i].to]>dist[now]+e[i].w){
                dist[e[i].to]=dist[now]+e[i].w; last[e[i].to]=i;
                if(!inq[e[i].to]){
                    q[++t]=e[i].to; inq[e[i].to]=1;
                }
        }
    }
    if(dist[T]==inf)return 0;else return 1;
}
ll flow()
{
    ll ans=inf;
    for(int i=T;i!=S;i=e[last[i]].from)ans=min(ans,e[last[i]].flow);
    for(int i=T;i!=S;i=e[last[i]].from)
        e[last[i]].flow-=ans,e[last[i]^1].flow+=ans;
    return ans;
}
int main()
{
    int i;
    n=read(); S=0; T=2*n+1;
    for(i=1;i<=n;i++)a[i]=read();
    memset(fir,255,sizeof(fir));
    ll p0=read(),t1=read(),p1=read(),t2=read(),p2=read();
    for(i=1;i<=n;i++){
        add(S,i,0,a[i]); add(i+n,T,0,a[i]);
        if(i+t1<=n)add(i,i+t1+n,p1,inf);
        if(i+t2<=n)add(i,i+t2+n,p2,inf);
        add(S,i+n,p0,inf);
        if(i<n)add(i,i+1,0,inf),add(i+n,i+n+1,0,inf);
    }
    ll ans=0;
    while(spfa())ans+=flow()*dist[T];
    printf("%lld\n",ans);
}
洛谷P1251

相关文章:

  • 2021-10-22
猜你喜欢
  • 2021-06-23
  • 2021-09-07
  • 2021-10-24
  • 2022-02-17
  • 2021-07-29
  • 2021-12-28
  • 2021-08-14
相关资源
相似解决方案