CF 739E

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/85220673

重复连不同价值的边帮助分类讨论
实数网络流需要eps

#include<bits/stdc++.h>
#define maxn 2005
#define inf 0x3f3f3f3f
using namespace std;

const double eps = 1e-7;
int n,a,b;
double p[maxn],u[maxn];
int info[maxn<<2],Prev[maxn*20],to[maxn*20],cap[maxn*20],cnt_e=1;
double cst[maxn*20];
inline void Node(int a,int b,int c,double d){ Prev[++cnt_e]=info[a],info[a] = cnt_e,to[cnt_e]=b,cap[cnt_e]=c,cst[cnt_e]=d; }
inline void Line(int a,int b,int c,double d){ Node(a,b,c,d),Node(b,a,0,-d); }	
int S,uS,pS,tot,T,dist,pre[maxn<<2];
double dis[maxn<<2];
bool inq[maxn<<2];

inline bool SPFA()
{
	memset(dis,-0x3f,sizeof dis);
	static queue<int>q;
	q.push(T),dis[T] = 0,inq[T] = 1;
	for(int now;!q.empty();)
	{
		now = q.front();q.pop();
		for(int j=info[now];j;j=Prev[j])
			if(cap[j^1] &&  dis[to[j]] - dis[now] - cst[j^1] < -eps)
			{
				dis[to[j]] = dis[now] + cst[j^1];
				pre[to[j]] = j^1;
				if(!inq[to[j]]) inq[to[j]] = 1 , q.push(to[j]);
			}
		inq[now] = 0;
	}
	return dis[S] >= 0;
}

int main()
{
	scanf("%d%d%d",&n,&a,&b);
	tot = 3 * n;
	S = ++tot ,  uS = ++tot , pS = ++tot , T = ++tot;
	Line(S,uS,b,0),Line(S,pS,a,0);
	for(int i=1;i<=n;i++) scanf("%lf",&p[i]),Line(pS,n+i,1,p[i]);
	for(int i=1;i<=n;i++) scanf("%lf",&u[i]),Line(uS,i,1,u[i]),Line(2*n+i,T,1,0),Line(2*n+i,T,1,-u[i]*p[i]),
		Line(i,2*n+i,1,0),Line(n+i,2*n+i,1,0);
		
	double cst = 0;
	while(SPFA())
	{
		int dist = 0x3f3f3f3f;
		for(int i=S;i!=T;i=to[pre[i]])
			dist = min(dist , cap[pre[i]]);
		for(int i=S;i!=T;i=to[pre[i]])
			cap[pre[i]] -= dist , cap[pre[i]^1] += dist;
		cst += dist * dis[S];
	}
	
	printf("%.4lf",cst);
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/85220673