【bzoj 1163&1339】 Mafia 【Baltic2008】

Description

匪徒准备从一个车站转移毒品到另一个车站,警方准备进行布控. 对于每个车站进行布控都需要一定的代价,现在警

方希望使用最小的代价控制一些车站,使得去掉这些车站后,匪徒无法从原定的初始点到达目标点

Input

第一行输入N,M代表车站的总个数,及有多少条双向边连接它们. 

2<=n<=200 , 1 <=m<=20000. 

第二行给出两个数a,b,代表匪徒的出发点及目标点.1<=a,b<=N,a<>b. 

再下来有N行,给出对第i个车站进行布控所需要的Money,其不超过10 000 000 

再下来M行,用于描述图的结构.

Output

最少需要多少Money

Sample Input

5 6
5 3
2
4
8
3
10
1 5
1 2
2 4
4 5
2 3
3 4

Sample Output

5

这道题是一个网络流,只要将每个点拆成两个u_1,u_2,在这两个点之间连一条权值为该点权值的边,对于原图上的边u\rightarrow v,连一条u_2\rightarrow v_1的权值为INF的边,然后跑一遍dinic即可,下面是程序:

#include<stdio.h>
#include<string.h>
#include<iostream>
#define min(a,b) a<b?a:b
using namespace std;
const int N=405,M=40005,INF=2e9;
struct queue{
	int l,r,a[N];
	void clear(){
		l=0,r=1;
	}
	bool empty(){
		return l+1==r;
	}
	void push(int x){
		a[r]=x;
		r=(r+1)%N;
	}
	void pop(){
		l=(l+1)%N;
	}
	int front(){
		return a[(l+1)%N];
	}
}q;
struct edge{
	int v,w,next;
}e[M<<1];
int head[N],k,d[N],s,t;
void add(int u,int v,int w){
	e[k]=(edge){v,w,head[u]};
	head[u]=k++;
	e[k]=(edge){u,0,head[v]};
	head[v]=k++;
}
bool BFS(){
	q.clear();
	memset(d,0,sizeof(d));
	d[s]=1;
	q.push(s);
	int i,u;
	while(!q.empty()){
		u=q.front();
		q.pop();
		for(i=head[u];i!=-1;i=e[i].next){
			if(!d[e[i].v]&&e[i].w){
				d[e[i].v]=d[u]+1;
				q.push(e[i].v);
			}
		}
	}
	return d[t];
}
int dfs(int u,int f){
	if(u==t||!f){
		return f;
	}
	int i;
	int use=0,t;
	for(i=head[u];i!=-1;i=e[i].next){
		if(d[e[i].v]==d[u]+1&&(t=dfs(e[i].v,min(e[i].w,f-use)))){
			e[i].w-=t;
			e[i^1].w+=t;
			use+=t;
			if(use==f){
				return f;
			}
		}
	}
	return use;
}
int dinic(){
	int ans=0;
	while(BFS()){
		ans+=dfs(s,INF);
	}
	return ans;
}
int main(){
	int n,m,i,x;
	memset(head,-1,sizeof(head));
	scanf("%d%d%d%d",&n,&m,&s,&t);
	s<<=1;
	t<<=1;
	++t;
	for(i=1;i<=n;i++){
		scanf("%d",&x);
		add(i<<1,(i<<1)+1,x);
	}
	while(m--){
		scanf("%d%d",&i,&x);
		add((i<<1)+1,x<<1,INF);
		add((x<<1)+1,i<<1,INF);
	}
	printf("%d\n",dinic());
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值