在写这篇文章之前,xxx已经写过了几篇关于改流量最小主题的文章,想要了解的朋友可以去翻一下之前的文章
题意:有n个都会,每一个都会有定一数量的察警,有一群小偷,从都会S,到T,问起码须要多少察警可以使小偷到不了T都会。
将每一个都会的察警数量当作流量,那么题问就转化成求S - T的最小割。
将每一个点拆成i , i + n ,流量是该点的值.然后跑一次最大流以可就了。
最大流最小割定理:恣意一个流络网的最大流量于等该络网的最小的割的量容。
#include <iostream> #include <cstdio> #include <algorithm> #include <string> #include <cmath> #include <cstring> #include <queue> #include <set> #include <vector> #include <stack> #include <map> #include <iomanip> #define PI acos(-1.0) #define Max 2005 #define inf 1<<28 #define LL(x) (x<<1) #define RR(x) (x<<1|1) #define REP(i,s,t) for(int i=(s);i<=(t);++i) #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define mp(a,b) make_pair(a,b) using namespace std; inline void readint(int &ret) { char c; do { c = getchar(); } while(c < '0' || c > '9'); ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); } int city[111] ; struct kdq { int s , e, l ,next ; } ed[1111111] ; int head[1111] ,num ; void add(int s ,int e ,int l ) { ed[num].s = s ; ed[num].e = e ; ed[num].l = l ; ed[num].next = head[s] ; head[s] = num ++ ; ed[num].s = e ; ed[num].e = s ; ed[num].l = 0 ; ed[num].next = head[e] ; head[e] = num ++ ; } int deep[1111] ; int qe[11111111] ; void init() { mem(head,-1) ; num = 0 ; } int S , T ; int dinic_bfs() { mem(deep,-1) ; deep[S] = 0 ; int h = 0 , t = 0 ; qe[h ++ ] = S ; while( h > t ) { int tt = qe[t ++ ] ; for (int i = head[tt] ; ~i ; i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(l > 0&& deep[e] == -1) { deep[e] = deep[tt] + 1 ; qe[ h ++ ] = e ; } } } return deep[T] != -1 ; } int dinic_dfs(int now, int f) { if(now == T)return f ; int flow = 0 ; for (int i = head[now] ; ~i ; i = ed[i].next ) { int e = ed[i].e ; int l = ed[i].l ; if(deep[e] == deep[now] + 1 && l > 0 && (f - flow ) > 0 ) { int mm = min(l,f - flow) ; int nn = dinic_dfs(e,mm) ; flow += nn ; ed[i].l -= nn ; ed[i ^ 1].l += nn ; } } if(!flow)deep[now] = -2 ; return flow ; } int dinic() { int flow = 0 ; while(dinic_bfs()) { flow += dinic_dfs(S,inf) ; } return flow ; } int main() { int t ; readint(t) ; while( t -- ) { int n , m , s, h ; readint(n) ; readint(m) ; readint(s) ; readint(h) ; init() ; S = 0 ,T = 2 * n + 1 ; REP(i,1,n) { int a ; readint(a) ; if(i != s && i != h) add(i , i + n , a) ; else add(i ,i + n ,inf) ;//点起出去的流量为inf,终点进来的流量也是inf } add(S,s,inf) ; add(h + n ,T,inf) ; REP(i,1,m) { int a , b ; readint(a) ; readint(b) ; add(a + n ,b ,inf) ;//双向边 add(b + n , a ,inf) ; } printf("%d\n",dinic()) ; } return 0; }
文章结束给大家分享下程序员的一些笑话语录: 问路
有一个驾驶热气球的人发现他迷路了。他降低了飞行的高度,并认出了地面 上的一个人。他继续下降高度并对着那个人大叫,“打扰一下,你能告诉我我 在哪吗?”
下面那个人说:“是的。你在热气球里啊,盘旋在 30 英尺的空中”。
热气球上的人说:“你一定是在 IT 部门做技术工作”。
“没错”,地面上的人说到,“你是怎么知道的?”
“呵呵”,热气球上的人说,“你告诉我的每件事在技术上都是对的,但对都没 有用”。
地面上的人说,“你一定是管理层的人”。
“没错”,热气球上的人说,“可是你是怎么知道的?”
“呵呵”,地面上的那人说到,“你不知道你在哪里,你也不知道你要去哪,你 总希望我能帮你。你现在和我们刚见面时还在原来那个地方,但现在却是我 错了”。