hdu 4289 Control 最小割最大流
http://acm.hdu.edu.cn/showproblem.php?pid=4289
题意:
有N个城市 M条无向边 有一些恐怖分子要从某一城市到另一城市 打算在某些城市安放一些SA 去抓住他 但若在某个城市安放SA需要一定费用 求一个集合使每个到达终点的路线肯定会经过其中一个点,而这个集合里面每个点都安放了SA,这样就能找到所有的恐怖分子,求该集合使费用最小。
思路:
网络流的题目做的还太少,对于这类题目还是不太敏感,没想到拆点建图。。。。
题目意思是求一个s-t割,求最小的费用肯定要求最小割了,又由于最小割等于最大流,所以我们只要用最大流求解即可,而这里建图是关键,这里将每个点拆成两个点(i ,i + n)然后i与i + n 的权值为该点小费,反向边为0 ,(x,y)则建立(x + n,y) (y + n,x)权值为inf 这里他们的反向边都为0;跑一边最大流算法就好了。。
View Code
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll __int64 #define inf 0x7f7f7f7f #define MOD 100000007 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 10000007 #define M 100007 #define N 407 using namespace std; //freopen("din.txt","r",stdin); struct node{ int v,w; int next; }g[N*N]; int head[N],ct; int q[maxn],level[N]; int n,m; void init(){ ct = 0; CL(head,-1); } void add(int u,int v,int w){ g[ct].v = v; g[ct].w = w; g[ct].next = head[u]; head[u] = ct++; g[ct].v = u; g[ct].w = 0; g[ct].next = head[v]; head[v] = ct++; } bool layer(int s,int e){ int l = 0; int r = 0; CL(level,-1); level[s] = 0; q[r] = s; while (l <= r){ int u = q[l++]; for (int i = head[u]; i != -1; i = g[i].next){ int v = g[i].v; if (level[v] == -1 && g[i].w > 0){ level[v] = level[u] + 1; if (v == e) return true; q[++r] = v; } } } return false; } int find(int s,int e){ int top = 1; int i; int ans = 0; while (top){ int u = (top == 1 ? s : g[q[top - 1]].v); if (u == e){ int MIN = inf,pos; for (i = 1; i < top; ++i){ int tp = q[i]; if (g[tp].w < MIN){ MIN = g[tp].w; pos = i; } } for (i = 1; i < top; ++i){ int tp = q[i]; g[tp].w -= MIN; g[tp^1].w += MIN; } ans += MIN; top = pos - 1; } else{ for (i = head[u]; i != -1; i = g[i].next){ int v = g[i].v; if (level[v] == level[u] + 1 && g[i].w > 0){ q[top++] = i; break; } } } if (i == -1){ top--; level[u] = -1; } } return ans; } int dinic(int s,int e){ int ans = 0; while (layer(s,e)){ ans += find(s,e); } return ans; } int main(){ //freopen("din.txt","r",stdin); int i; int s,e,val; int x,y; while (~scanf("%d%d",&n,&m)){ init(); scanf("%d%d",&s,&e); e = e + n; for (i = 1; i <= n; ++i){ scanf("%d",&val); add(i,i + n,val); } for (i = 0; i < m; ++i){ scanf("%d%d",&x,&y); add(x + n,y,inf); add(y + n,x,inf); } printf("%d\n",dinic(s,e)); } return 0; }