您的位置:首页 > 理论基础 > 计算机网络

uva 563 - Crimewave 网络流

2015-12-06 15:05 633 查看
题目链接

有一个n*m的图, 里面有q个人, 每个点只能走一次, 问这q个人是否都能够走出这个图。



对于每个人, 建边(s, u, 1), 对于每个边界的格子, 建边(u', t, 1), 对于其他格子, 建边(u, u', 1), 以及(u', v, 1), v是它四周的格子。

对于求出的最大流, 如果等于人数, 则可以走出。

#include<bits/stdc++.h>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, a, n) for(int i = a; i<n; i++)
#define ull unsigned long long
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int mod = 1e9+7;
const int inf = 1061109567;
const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
const int maxn = 2e6+5;
int num, q[maxn*5], head[maxn*2], dis[maxn*2], s, t;
struct node
{
int to, nextt, c;
node(){}
node(int to, int nextt, int c):to(to), nextt(nextt), c(c){}
}e[maxn*2];
int bfs() {
mem(dis);
int st = 0, ed = 0;
dis[s] = 1;
q[ed++] = s;
while(st<ed) {
int u = q[st++];
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(!dis[v]&&e[i].c) {
dis[v] = dis[u]+1;
if(v == t)
return 1;
q[ed++] = v;
}
}
}
return 0;
}
int dfs(int u, int limit) {
int cost = 0;
if(u == t)
return limit;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(e[i].c&&dis[v] == dis[u]+1) {
int tmp = dfs(v, min(e[i].c, limit-cost));
if(tmp>0) {
e[i].c -= tmp;
e[i^1].c += tmp;
cost += tmp;
if(cost == limit)
break;
} else {
dis[v] = -1;
}
}
}
return cost;
}
int dinic() {
int ans = 0;
while(bfs()) {
ans += dfs(s, inf);
}
return ans;
}
void add(int u, int v, int c) {
e[num] = node(v, head[u], c); head[u] = num++;
e[num] = node(u, head[v], 0); head[v] = num++;
}
void init() {
mem1(head);
num = 0;
}
int main()
{
int T, m, n, x, y, q;
cin>>T;
while(T--) {
init();
scanf("%d%d%d", &n, &m, &q);
int nm = n*m;
s = 2*nm, t = s+1;
for(int i = 1; i<=q; i++) {
scanf("%d%d", &x, &y);
x--, y--;
add(s, x*m+y, 1);
}
for(int i = 0; i<n; i++) {
for(int j = 0; j<m; j++) {
int ij = i*m+j;
add(ij, ij+nm, 1);
if(i==0||j==0||i==n-1||j==m-1) {
add(ij+nm, t, 1);
} else {
for(int k = 0; k<4; k++) {
x = i + dir[k][0];
y = j + dir[k][1];
add(ij+nm, x*m+y, 1);
}
}
}
}
if(dinic() == q)
cout<<"possible"<<endl;
else
cout<<"not possible"<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: