版权声明:本文为博主原创文章,未经博主允许必须转载。 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);
}