题意:一个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;
}