luogu_P1315 观光公交

最小费用 最大流

我看了很久题解还是不会.等以后学好MCMF一定来写这道.

c o d e

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 8010
#define M 10010
#define inf 0x3f3f3f3f
using namespace std;
struct line{
    int to,w,c,next;
}a[N];
struct node{
	int t,l,r;
}peo[M];
int sd,s,t,d[N],down[N],last[N],get[N],k;
int tot,n,m,f[N],ls[N],tail,answer;
int state[N],x,y,w,c,ans,head,pre[N];
bool v[N];
void addl(int x,int y,int w,int c)
{
    a[++tot].to=y;a[tot].w=w;a[tot].c=c;
    a[tot].next=ls[x];ls[x]=tot;
    a[++tot].to=x;a[tot].w=0;a[tot].c=-c;
    a[tot].next=ls[y];ls[y]=tot;
}
bool spfa()
{
    memset(f,0x3f,sizeof(f));
    memset(v,0,sizeof(v));
    head=0;tail=1;v[s]=true;
    state[1]=s;f[s]=0;
    while (head!=tail)
    {
        head=head%N+1;
        int x=state[head];
        for (int q=ls[x];q;q=a[q].next)
        {
            int y=a[q].to;
            if (a[q].w&&f[x]+a[q].c<f[y])
            {
                f[y]=f[x]+a[q].c;
                pre[y]=q;
                if (!v[y])
                {
                    v[y]=true;
                    tail=tail%N+1;
                    state[tail]=y;
                }
            }
        }
        v[x]=false;
    }
    if (f[t]>=707406378) return 0;
    else return 1;
}
void upway()
{
    int k=2147483647,now=t;
    while (now!=s)
    {
        k=min(k,a[pre[now]].w);
        now=a[pre[now]^1].to;
    }
    ans+=f[t]*k;now=t;
    answer+=k;
    while (now!=s)
    {
        a[pre[now]].w-=k;
        a[pre[now]^1].w+=k;
        now=a[pre[now]^1].to;
    }
}
int main()
{
	freopen("data.in","r",stdin);
	//freopen("data.out","w",stdout);
	tot=1;
	scanf("%d%d%d",&n,&m,&k);
	s=n*2+1,sd=n*2+2,t=n*2+3;
	for(int i=1;i<n;i++)
	  scanf("%d",&d[i]);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&peo[i].t,&peo[i].l,&peo[i].r);
		down[peo[i].r]++;last[peo[i].l]=max(last[peo[i].l],peo[i].t);
	}
	for(int i=1;i<n;i++)
	  get[i+1]=max(get[i],last[i])+d[i];
	for(int i=1;i<=m;i++)
	  ans+=get[peo[i].r]-peo[i].t;
	addl(s,sd,k,0);
	for(int i=1;i<n;i++)
	{
		addl(i,i+n,max(get[i]-last[i],0),0);
		addl(i+n,i+1,inf,-down[i+1]);
		addl(sd,i+n,d[i],0);
		addl(i+1,t,inf,0);
	}
    while (spfa())
      upway();
	printf("%d",ans);
}
原文地址:https://www.cnblogs.com/GUOGaby/p/14038194.html