题意:一个s*a条线的网格,网格线的交点出是银行(共s*a个),晚上若干个银行会被抢,罪犯要逃跑到网格边界以外。为了安全起见,所有的罪犯不能经过同一个交点,问存在这样的逃跑路径吗。
思路:最大流,把每个点拆成两个,一个用来入,一个用来出。建图源点->被抢银行入->被抢银行出->相邻银行入->...->边界->汇点。数据量有点大,不能用二维数组来存,改成vector。
#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>
#define INF 1000000000
using namespace std;
int s,a,b;
vector<int> E[5010];
vector<int> c[5010];
vector<int> f[5010];
int x[2510];
int y[2510];
bool vis[5010];
bool isEdge(int i){//判断边界
if(i%2)return false;
i/=2;
if(i<=a||i>a*(s-1))return true;
if(i%a==1||i%a==0)return true;
return false;
}
bool dfs(int start){
vis[start]=1;
if(isEdge(start))return true;
for(int i=0;i<E[start].size();i++){
if( !vis[E[start][i]] && (c[start][i]-f[start][i])>0 ){
int key=0;
for(int j=0;j<E[E[start][i]].size();j++){
if(E[E[start][i]][j]==start){
key=j;
break;
}
}
if(dfs(E[start][i])){
f[start][i]++;
f[E[start][i]][key]--;
return true;
}
}
}
return false;
}
int main(){
int p;
scanf("%d",&p);
while(p--){
for(int i=0;i<5010;i++){
E[i].clear();
c[i].clear();
f[i].clear();
}
scanf("%d%d%d",&s,&a,&b);
for(int i=1;i<=b;i++){
scanf("%d%d",&x[i],&y[i]);
}
//建图
for(int i=1;i<=a*s*2;i++){
if(isEdge(i))continue;
if(i%2){//入点
E[i].push_back(i+1);
c[i].push_back(1);
f[i].push_back(0);
E[i+1].push_back(i);
c[i+1].push_back(0);
f[i+1].push_back(0);
}else{//出点
E[i].push_back(i-a*2-1);
E[i].push_back(i+a*2-1);
E[i].push_back(i-3);
E[i].push_back(i+1);
c[i].push_back(1);c[i].push_back(1);c[i].push_back(1);c[i].push_back(1);
f[i].push_back(0);f[i].push_back(0);f[i].push_back(0);f[i].push_back(0);
E[i-a*2-1].push_back(i);
E[i+a*2-1].push_back(i);
E[i-3].push_back(i);
E[i+1].push_back(i);
c[i-a*2-1].push_back(0);c[i+a*2-1].push_back(0);
c[i-3].push_back(0);c[i+1].push_back(0);
f[i-a*2-1].push_back(0);f[i+a*2-1].push_back(0);
f[i-3].push_back(0);f[i+1].push_back(0);
}
}
int ans=0;
for(int i=1;i<=b;i++){
memset(vis,0,sizeof(vis));
if(dfs( ((x[i]-1)*a+y[i])*2-1 )){
ans++;
}
}
if(b-ans){
printf("not possible\n");
}else{
printf("possible\n");
}
}
return 0;
}
本文探讨利用最大流算法解决在一个网状结构中,多个银行被抢劫后,罪犯如何找到安全逃离路径的问题。通过将每个节点拆分为入点和出点,并建立相应的边和容量限制,实现从源点到汇点的最大流量计算,从而判断是否存在安全的逃离路径。此方法适用于解决类似问题,如物流网络中的货物分配或电力网络中的能源传输。
784

被折叠的 条评论
为什么被折叠?



