最大权闭合图 zoj2930

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;

int const nMax = 310;
int const oo = 0x7fffffff;

int first[nMax],now[nMax],f[nMax*nMax],to[nMax*nMax],nxt[nMax*nMax];
int n,m,e;
int src,sink;

void init(){
	src = 0;sink = n+1;
	for(int i=0;i<=n+1;i++) first[i] = -1;
	e = 0;
}

void addedge(int u,int v,int val){
	to[e] = v; f[e] = val; nxt[e] = first[u]; first[u] = e; e++;
	to[e] = u; f[e] = 0;   nxt[e] = first[v]; first[v] = e; e++;
}

int que[nMax*nMax],head,tail,dist[nMax];
bool bfs(){
	for(int i=0;i<=n+1;i++) dist[i] = -1;
	head = tail = 0;
	dist[que[tail++] = src] = 0;
	while(head < tail) {
		int u = que[head++];
		for(int i=first[u],v;i != -1;i=nxt[i]) if(f[i] && dist[v=to[i]] == -1){
			dist[v] = dist[u] + 1;
			que[tail++] = v;
			if(v == sink) return 1;
		}
	}
	return 0;
}

int dfs(int u,int add){
	if(u == sink) return add;
	for(int &i = now[u],v;i != -1;i=nxt[i]) if(f[i] && dist[v=to[i]] == dist[u]+1){
		int delta = dfs(v,min(f[i],add));
		if(delta > 0) {
			f[i] -= delta;
			f[i^1] += delta;
			return delta;
		}
	}
	return 0;
}

int dinic(){
	int flow =  0;
	while(bfs()){
		for(int i=0;i<=n+1;i++) now[i] = first[i];
		while(1){
			int delta = dfs(src,oo);
			if(delta <= 0) break;
			flow += delta;
		}
	}
	return flow;
}


int adv[nMax],delay[nMax],sum;
void sovle(){
	sum = 0;
	int sum2=0;
	for(int i=1;i<=n;i++) scanf("%d",&adv[i]),sum+=adv[i];
	for(int i=1;i<=n;i++) scanf("%d",&delay[i]);
	scanf("%d",&m);
	init();
	for(int i=0,u,v;i<m;i++){
		scanf("%d%d",&u,&v);
		addedge(u,v,oo);
	}
	for(int i=1;i<=n;i++)
		if(adv[i]-delay[i]>0) addedge(src,i,adv[i]-delay[i]),sum2+=adv[i]-delay[i];
		else addedge(i,sink,delay[i]-adv[i]);
	int flow = dinic();
	flow = sum2-flow;
	bfs();
	sum-=flow;
	int ans = 0;
	for(int i =1;i<=n;i++)if(-1 == dist[i]){
		ans++;
	}
	printf("%d %d\n",sum,ans);
}

int main(){
    //freopen("a.txt","r",stdin);
	while(~scanf("%d",&n) && n){
		sovle();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值