BestCoder Round #67
【BestCoder Round #75 1004】King's Game

【BestCoder Round #75 1005】King's Pilots

Zarxdy34 posted @ 2016年3月13日 08:52 in BestCoder with tags 费用流 , 468 阅读

  费用流建模和BZOJ1221,网络流24题里的餐巾计划是差不多的。

  但是由于刚开始有k的飞行员,所以要从S向Y1连一条容量为k费用为0的边,并且每个Yi到Yi+1连一条容量为无穷大费用为0的边,以使用这k个飞行员。

 

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=210,maxv=410,inf=~0U>>1;

int head[maxv<<1],net[maxv<<4],E[maxv<<4],F[maxv<<4],C[maxv<<4],Ecnt;
int P[maxn];
int s[maxn],t[maxn];
int n,k,m,p,q;
int S,T;

void Add_Edge(int x,int y,int flow,int cost)
{
	net[++Ecnt]=head[x];head[x]=Ecnt;E[Ecnt]=y;F[Ecnt]=0;C[Ecnt]=cost;
	net[++Ecnt]=head[y];head[y]=Ecnt;E[Ecnt]=x;F[Ecnt]=flow;C[Ecnt]=-cost;
}
int vis[maxv];
int Q[maxv],qhead,qtail;
int dis[maxv];
int prev[maxv];

int inc(int x) {return x==maxv-1?0:x+1;}
int dec(int x) {return x==0?maxv-1:x-1;}

bool Spfa(int st,int ed)
{
	memset(vis,0,sizeof(vis));
	memset(dis,0x7F,sizeof(dis));
	Q[qhead=qtail=0]=st;
	vis[st]=1;dis[st]=0;
	while (qhead!=inc(qtail))
	{
		int x=Q[qhead];
		qhead=inc(qhead);
		vis[x]=0;
		for (int i=head[x];i;i=net[i]) if (F[i] && dis[E[i]]>dis[x]-C[i])
		{
			dis[E[i]]=dis[x]-C[i];
			if (!vis[E[i]])
				if (qhead!=inc(qtail) && dis[Q[qhead]]>dis[E[i]]) Q[qhead=dec(qhead)]=E[i];else Q[qtail=inc(qtail)]=E[i];
			vis[E[i]]=1;
		}
	}
	return dis[ed]!=0x7F7F7F7F;
}

int DFS(int x,int flow,int &res)
{
	vis[x]=1;
	if (x==T) return flow;
	int rest=flow;
	for (int i=head[x];i && rest;i=net[i])
		if (dis[E[i]]==dis[x]-C[i] && F[i^1] && !vis[E[i]])
		{
			int d=DFS(E[i],min(rest,F[i^1]),res);
			res+=d*C[i];
			rest-=d;F[i]+=d;F[i^1]-=d;
		}
	return flow-rest;
}

void Min_Cost_Flow()
{
	int res=0;
	while (Spfa(T,S))
	{
		vis[T]=1;
		while (vis[T])
		{
			memset(vis,0,sizeof(vis));
			DFS(S,inf,res);
		}
	}
	printf("%d\n",res);
}

int main()
{
	int TT;
	scanf("%d",&TT);
	while (TT--)
	{
		memset(head,0,sizeof(head));
		Ecnt=1;
		scanf("%d%d",&n,&k);
		for (int i=1;i<=n;i++) scanf("%d",&P[i]);
		scanf("%d%d%d",&m,&p,&q);
		int psum=0;for (int i=1;i<p;i++) psum+=P[i];if (psum>k) {puts("No solution");continue;}
		for (int i=1;i<=m;i++) scanf("%d%d",&s[i],&t[i]);
		S=2*n+1;T=S+1;
		Add_Edge(S,n+1,k,0);
		for (int i=1;i<=n;i++) Add_Edge(S,i,P[i],0);
		for (int i=1;i<=n;i++) Add_Edge(i+n,T,P[i],0);
		for (int i=1;i<=n;i++)
			for (int j=1;j<=m;j++)
				if (t[j]+i<=n) Add_Edge(i,i+n+t[j],inf,s[j]);
		for (int i=1;i<n;i++) Add_Edge(i,i+1,inf,0),Add_Edge(i+n,i+n+1,inf,0);
		for (int i=p;i<=n;i++) Add_Edge(S,i+n,inf,q);
		Min_Cost_Flow();
	}
	return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter