首页 > 代码库 > 【East!模拟赛】【Round1】【BZOJ2324】营救皮卡丘 有下界的费用流

【East!模拟赛】【Round1】【BZOJ2324】营救皮卡丘 有下界的费用流

题意:不多说了。

题解:

begin

    首先想到:我们要强制走过那些下界。

    怎么强制呢?我们把费用赋为-inf!!看他走不走!

    然后费用的初值就需要把这些扣掉的inf加回来。

end.


贴代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 500
#define M 201000
#define inf 2000000
using namespace std;
struct KSD
{
	int u,v,w,len,next;
}e[M<<3];/*瞎开的大小*/
int head[N],cnt;/*网络流图*/
void add(int u,int v,int w,int len)
{
	++cnt;
	e[cnt].u=u,e[cnt].v=v,e[cnt].w=w;
	e[cnt].len=len,e[cnt].w=w;
	e[cnt].next=head[u],head[u]=cnt;
}
int map[N][N];/*预处理的floyd图*/
int n,m,p;

int S,s,T;
long long dist[N],fee;
int pre[N];
bool in[N];

long long spfa()
{
	memset(dist,0x3f,sizeof(dist));
	queue<int>q;
	int i,u,v;
	dist[S]=0;
	in[S]=1;
	q.push(S);
	while(!q.empty())
	{
		u=q.front();q.pop();in[u]=0;
		for(i=head[u];i;i=e[i].next)
		{
			v=e[i].v;
			if(!e[i].len)continue;
			if(dist[v]>dist[u]+e[i].w)
			{
				dist[v]=dist[u]+e[i].w;
				pre[v]=i;
				if(!in[v])
				{
					in[v]=1;
					q.push(v);
				}
			}
		}
	}
	return dist[T];
}
void handle()
{
	for(int i=pre[T];i;i=pre[e[i].u])
	{
		e[i].len-=1;
		e[i^1].len+=1;
	}
}
void build()
{
	int i,j;
	cnt=1;
	s=0,S=2*n+1,T=2*n+2;
	add(S,s,0,p);
	add(s,S,0,0);
	add(s,T,0,p);
	add(T,s,0,0);
	for(i=1;i<=n;i++)
	{
		add(s,i*2-1,map[s][i],1);
		add(i*2-1,s,-map[s][i],0);

		add(i*2-1,i*2,-inf,1);
		add(i*2,i*2-1,inf,0);

		add(i*2,T,0,1);
		add(T,i*2,0,0);
	}
	for(i=1;i<=n;i++)
	{
		for(j=i+1;j<=n;j++)
		{
			add(i*2,j*2-1,map[i][j],1);
			add(j*2-1,i*2,-map[i][j],0);
		}
	}
}
int main()
{
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
	int i,j,k;
	int a,b,c;
	scanf("%d%d%d",&n,&m,&p);
	memset(map,0x3f,sizeof(map));
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		map[a][b]=map[b][a]=min(map[a][b],c);
	}
	for(i=0;i<=n;i++)map[i][i]=0;
	for(k=0;k<=n;k++)for(i=0;i<=n;i++)for(j=0;j<=n;j++)if(k<=i||k<=j)map[i][j]=min(map[i][j],map[i][k]+map[k][j]);//floyd
	build();
	fee=inf*n;
	long long temp;
	while(temp=spfa(),temp<0x3f3f3f3f3f3f3f3fll)
	{
		fee+=temp;
		handle();
	}
	cout<<fee<<endl;
	fclose(stdin);
	fclose(stdout);
	return 0;
}


【East!模拟赛】【Round1】【BZOJ2324】营救皮卡丘 有下界的费用流