PO J3308-Paratroopers---网络流

构建一个二分图,行坐标为S点集,纵坐标我T点集。令s=0,连接所有S,t=n+m+1,所有T连接t。

求此二分图的最小割,即最大流。

乘法需要 转换为 log()在求和,最后exp()回来


#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<queue>
using namespace std;

int n,m,l;
double cap[110][110],flow[110][110],a[110];
int pre[110];

double EK(int s,int t)
{
	queue<int> q;
	double f=0;
	memset(flow,0,sizeof(flow));
	memset(pre,0,sizeof(pre));
	while(1){
		q.push(s);
		
		memset(a,0,sizeof(a));
		
		a[s]=99999.0;
		while(!q.empty()){
			int u=q.front();
			q.pop();
			for(int v=0;v<=n+m+1;v++){
				if(!a[v] && cap[u][v] > flow[u][v]){
					pre[v]=u;
					a[v]=min(a[u],cap[u][v]-flow[u][v]);
					q.push(v);
				}
			}
		}
		if(a[t]==0) break;
		for(int i=t;i!=s;i=pre[i]){
			flow[pre[i]][i] += a[t];
			flow[i][pre[i]] -= a[t];
		}
		f += a[t];
	}
	return exp(f);
}
int main()
{
	int t;
	int i,j,k,b,c;
	double tt;
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d",&n,&m,&l);
		memset(cap,0,sizeof(cap));
		for(i=1;i<=n;i++){
			scanf("%lf",&tt);
			cap[0][i]=log(tt);
		}
		for(i=n+1;i<=n+m;i++){
			scanf("%lf",&tt);
			cap[i][n+m+1]=log(tt);
		}
		while(l--){
			scanf("%d%d",&b,&c);
			cap[b][c+n]=99999.0;
		}
		double ans=EK(0,n+m+1); 
		printf("%.4lf\n",ans);
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值