题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289
题意:给你n个点,m条边,一个起点,一个终点,意思是一群***从起点出发到终点作案,要求你在一些点建立检查点,用最小的花费使得***到达不了终点。
由于是每个点上有花费,所以把点拆开,设置成 当前点到新点的距离为当前点的花费
即add(i,i + n,c);
m条边为
add(u+n,v,INF);
add(v+n,u,INF);
起点为s,终点为 t+n
其他就是最大流模板
#include <algorithm>
#include <vector>
#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX = (1ll << 31) - 1;
const int mavn = 4e5+5;
const int maxn = 1e5+5;
#define ll long long
struct Edge{
int to;
ll dis;
int rev;
Edge(){}
Edge(int to,ll d,int c):to(to),dis(d),rev(c){}
} ;
vector<Edge> v[maxn];
int n, m, s, t;
struct node {
int u,v,d;
ll c;
node(){}
node(int a,int b,ll c,int d):u(a),v(b),c(c),d(d){}
}pos[mavn];
void addEdge(int from, int to, ll dis){
v[from].push_back(Edge(to, dis,v[to].size()));
v[to].push_back(Edge(from, 0,v[from].size()-1));
}
int d[mavn],cnt, cur[mavn];
ll DFS(int u, ll flow){
if (u == t || !flow) return flow;
ll ans = 0, tmp_flow;
for (int& i = cur[u]; i < v[u].size(); i++){
int to = v[u][i].to;
if (d[to] == d[u] + 1 && v[u][i].dis > 0){
tmp_flow = DFS(to, min(flow, v[u][i].dis));
if(tmp_flow > 0) {
flow -= tmp_flow;
v[u][i].dis -= tmp_flow;
ans += tmp_flow;
v[to][v[u][i].rev].dis += tmp_flow;
if (!flow)
break;
}
}
}
if (!ans) d[u] = -1;
return ans;
}
bool BFS(){
memset(d,-1,sizeof(d));
queue<int> que;
que.push(s);
d[s] = 0;
int u, _new;
while (!que.empty()){
u = que.front();
que.pop();
for (int i = 0; i < v[u].size(); i++){
_new = v[u][i].to;
if (d[_new] == -1 && v[u][i].dis > 0){
d[_new] = d[u] + 1;
que.push(_new);
}
}
}
return (d[t] != -1);
}
ll dinic(){
ll max_flow = 0;
while (BFS()){
memset(cur,0,sizeof(cur));
ll tt;
while((tt = DFS(s,MAX)) > 0) max_flow += tt;
}
return max_flow;
}
int T;
int main(){
while(scanf("%d%d",&n,&m)!=EOF) {
scanf("%d%d",&s,&t);
for(int i=1;i<=n;i++) {
ll c;
scanf("%lld",&c);
addEdge(i,i+n,c);
}
for(int i=1 ; i<=m ; ++i){
int a,b;
scanf("%d %d",&a,&b);
addEdge(a+n,b,MAX);
addEdge(b+n,a,MAX);
}
t = t + n;
printf("%lld\n",dinic());
for(int i=0;i<=n*2;i++) v[i].clear();
}
return 0;
}