您的位置:首页 > 运维架构

ural 1277. Cops and Thieves【最小割】

2013-07-31 13:16 357 查看


ural 1277. Cops and Thieves【最小割】

分类: 【图论专辑】2010-07-28
00:00 210人阅读 评论(2) 收藏 举报

/* 小偷要从S城市到T城市偷东西,每个城市需要不同数量的警察来看守,现在给出警察数量,看能不能成功阻止小偷

* 题意即是求最小割,但是由于给出的是每个点的容量,所以需要将每个点拆为两个点,之间连边,容量为点的容量,

* 两个城市如果相连则容量置为无穷大。然后求最大流看是否大于已有警察数。拆点的时候可以将点i拆为2*i-1和2*i

* 这个题最后一组数据源点和汇点是一个点,很变态,需要特别考虑。。。@@

*/

[cpp] view
plaincopy

#include <cstdio>

#include <cstring>

#define FOR(a,b) for(int i = a; i<= b; ++i)

#define INF 0x1f1f1f1f

#define MAXN 250

using namespace std;

int n,m,src,sink,num;

int cap[MAXN][MAXN],f[MAXN][MAXN],level[MAXN],q[MAXN];

inline bool dinic_bfs(){

int queue[MAXN];

memset(level,-1,sizeof(level));

int head = 0,tail = 0;

queue[tail++] = src;

level[src] = 0;

while(tail > head){

int tep = queue[head++];

for(int i = 1;i <= n; ++i){

if(level[i] == -1 && cap[tep][i] > f[tep][i]){

level[i] = level[tep] + 1;

queue[tail++] = i;

}

}

}

return level[sink] != -1;

}

inline int dinic(){

int cur,k,m,tail,maxflow = 0, *stack = q;

while(dinic_bfs()){

tail = 0;

stack[tail++] = src;

while(tail){

cur = stack[tail-1];

if(cur == sink){

m = INF;

for(int i = 1;i < tail; ++i){

if(m > cap[stack[i-1]][stack[i]]-f[stack[i-1]][stack[i]]){

m = cap[stack[i-1]][stack[i]]-f[stack[i-1]][stack[i]];

k = i;

}

}

maxflow += m;

for(int i = 1;i < tail; ++i){

f[stack[i-1]][stack[i]] += m;

f[stack[i]][stack[i-1]] -= m;

}

tail = k;

}

else{

int i;

for(i = 1;i <= n; ++i){

if(level[i] == level[cur] + 1 && cap[cur][i] > f[cur][i]){

stack[tail++] = i;

break;

}

}

if(i == n+1){

level[cur] = -1;

--tail;

}

}

}

}

return maxflow;

}

int main()

{

while(scanf("%d",&num) != EOF){

int k;

scanf("%d%d%d%d",&n,&m,&src,&sink);

memset(cap,0,sizeof(cap));

memset(f,0,sizeof(f));

for(int i = 1;i <= n; ++i){

scanf("%d",&k);

cap[2*i-1][2*i] = k; // 将一个点拆为两个点,容量为点的容量

cap[2*i][2*i-1] = k;

}

while(m--){

int u,v;

scanf("%d%d",&u,&v);

cap[2*u][2*v-1] = INF;

cap[2*v][2*u-1] = INF;

}

n = 2*n; src = 2*src; sink = 2*sink - 1;

int ans = dinic();

if(ans > num || sink+1 == src)//如果最大流大于警察数或者源点汇点是一个点

printf("NO/n");

else printf("YES/n");

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: