HOJ 2634 How to earn more

【题目分析】

    这是一道最小割的应用题,首先从源点向每一个任务连一条容量为能获得的钱的边,然后把每一个需要雇的人向汇点连一条为Vi的边,最后把每一个任务向需要的人连一条容量为INF的边,然后跑一遍最大流,那么割掉(满流)的部分如果在左侧代表我不做这个任务,那么用所有任务的价值和前去最大流(不做的那一部分) ,就是最大的价值了。


因为HOJ崩了,无法提交,所以并没有测试。但是样例过了,应该没有什么问题了。有时间再测吧

【代码】

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
const int INF=1000000;
#define M1(a) memset(a,-1,sizeof a)
#define M0(a) memset(a,0,sizeof a)
#define F(i,j,k) for (int i=j;i<=k;++i)
#define maxn 50010
int sum=0,en=0,tt,u[maxn],v[maxn],h[maxn],ne[maxn],map[maxn],f[maxn],S,T;
inline void add(int a,int b,int r)
{
	u[en]=a;v[en]=b;ne[en]=h[a];f[en]=r;h[a]=en++;
	u[en]=b;v[en]=a;ne[en]=h[b];f[en]=0;h[b]=en++;
}
inline bool tell()
{
	memset(map,-1,sizeof map);
	int que[501];
	int head=0,tail=0;
	que[tail++]=S;
	map[S]=0;
	while (head<tail){
		int u=que[head++];
		for (int i=h[u];i!=-1;i=ne[i]){
			if (map[v[i]]==-1&&f[i]){
				map[v[i]]=map[u]+1;
				que[tail++]=v[i];
			}
		}
	}
	if (map[T]!=-1) return true;
	else return false;
}
inline int zeng (int k,int now)
{
	if (k==T) return now;
	int r=0;
	for (int i=h[k];i!=-1&&now>r;i=ne[i]){
		if (map[k]+1==map[v[i]]&&f[i]!=0){
			int t=zeng(v[i],min(now-r,f[i]));
			f[i]-=t;f[i^1]+=t;r+=t;
		}
	}
	if (!r) map[k]=-1;
	return r;
}
inline int dinic()
{
	int r=0,t;
	while (tell()) while (t=zeng(S,INF)) r+=t;
	return r; 
}
inline void reset()
{
	M1(u);M1(v);M1(h);M1(ne);
}
inline void solve()
{
	int n,m;
	scanf("%d%d",&n,&m);
	S=0;T=n+m+1;
	for (int i=1;i<=n;++i){
		int x;
		scanf("%d",&x);
		sum+=x;
		add(S,i,x);
	}
	for (int i=1;i<=m;++i){
		int x;
		scanf("%d",&x);
		add(i+n,T,x);
	}
	for (int i=1;i<=n;++i){
		int x;
		scanf("%d",&x);
		for (int j=1;j<=x;++j){
			int y;
			scanf("%d",&y);
			add(i,y+1+n,INF);
		}
	}
	cout<<sum-dinic();
}
int main()
{
	scanf("%d",&tt);
	F(i,1,tt) {reset();solve();}
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值