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
这道题是一个网络流,只要将每个点拆成两个,在这两个点之间连一条权值为该点权值的边,对于原图上的边,连一条的权值为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;
}