#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<cmath>
#pragma warning(disable:4996)
using std::cin;
using std::cout;
using std::endl;
using std::stringstream;
using std::string;
using std::vector;
using std::list;
using std::pair;
using std::set;
using std::multiset;
using std::map;
using std::multimap;
using std::stack;
using std::queue;
using std::priority_queue;
const int infinity = 1000000000;
template<typename ElemType>
class Point
{
public:
ElemType x, y;
Point()
{
x = y = 0;
}
Point(const ElemType &X, const ElemType &Y)
{
x = X, y = Y;
}
/*
friend Point<ElemType>operator+(const Point &point)
{
return{ x + point.x,y + point.y };
}
friend Point<ElemType>operator-(const Point &point)
{
return{ x - point.x,y - point.y };
}*/
void operator+=(const Point &point)
{
x += point.x, y += point.y;
}
void operator-=(const Point &point)
{
x -= point.x, y -= point.y;
}
};
class Edge
{
public:
int from, to, flow, capacity;
Edge(const int &v, const int &a, const int &c, const int &f)
{
from = v, to = a, capacity = c, flow = f;
}
};
class Network
{
private:
int vexnum, edgenum;//表示顶点个数和边个数
int source, destination;//表示源点和汇点
int bank;
int max_flow;//最大流
vector<Edge>edge;//边数的两倍
vector<vector<int>>adjList;//邻接表
public:
void addEdge(const int &from, const int &to, const int &capacity)
{
edge.push_back({ from,to,capacity,0 });
adjList[from].push_back(edge.size() - 1);
edge.push_back({ to,from,0,0 });
adjList[from].push_back(edge.size() - 1);
//cout << from << ' ' << to << endl;
//cout << to << ' ' << from << endl;
}
Network()
{
max_flow = 0;
vector<Point<int>>increment;
increment.push_back({ -1,0 });
increment.push_back({ 1,0 });
increment.push_back({ 0,-1 });
increment.push_back({ 0,1 });
int row, column;
cin >> row >> column >> bank;
vexnum = 2 * row*column + 2;//点+源点+汇点
source = 0, destination = vexnum - 1;
adjList.resize(vexnum);
//拆点
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= column; j++)
{
auto first = (i - 1)*column + j;//前点()
auto second = first + row*column;//后点
addEdge(first, second, 1);//建立前点和后点的关系
for (int k = 0; k < 4; k++)
{
//如果该点不在边上
auto x = i + increment[k].x;auto y = j + increment[k].y;
if (x >= 1 && x <= row&&y >= 1 && y <= column)
{
//具体化这个相邻点
//找到该点的前点
auto First = (x - 1)*column + y;
//连接当前点的后点和相邻点的前点
addEdge(second, First, 1);
}
else
{
addEdge(second, destination, 1);
}
}
}
}
//读入银行位置
for (int i = 0; i < bank; i++)
{
int x, y; cin >> x >> y;
auto first = (x - 1)*column + y;//前点
addEdge(source, first, 1);
}
}
void getMaxFlow()
{
vector<int>path(vexnum);
while (1)
{
vector<int>augument(vexnum);
queue<int>Q;
Q.push(source);
augument[source] = infinity;
while (!Q.empty())
{
auto x = Q.front();
Q.pop();
for (int i = 0; i < adjList[x].size(); i++)
{
auto e = edge[adjList[x][i]];
if (!augument[e.to] && e.capacity>e.flow)
{
path[e.to] = adjList[x][i];
augument[e.to] = std::min(augument[x], e.capacity - e.flow);
Q.push(e.to);
}
}
if (augument[destination])
{
break;
}
}
if (!augument[destination])
{
break;
}
for (auto u = destination; u != source; u = edge[path[u]].from)
{
edge[path[u]].flow += augument[destination];
edge[path[u] ^ 1].flow -= augument[destination];
}
max_flow += augument[destination];
}
}
void print()
{
if (max_flow == bank)
{
cout << "possible" << endl;
}
else
{
cout << "not possible" << endl;
}
}
};
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int n; cin >> n;
while (n--)
{
Network network;
network.getMaxFlow();
network.print();
}
return 0;
}
<pre name="code" class="cpp">#include<iostream>
#include<sstream>
#include<string>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<numeric>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#pragma warning(disable:4996)
using std::cin;
using std::cout;
using std::endl;
using std::stringstream;
using std::string;
using std::vector;
using std::list;
using std::pair;
using std::set;
using std::multiset;
using std::map;
using std::multimap;
using std::stack;
using std::queue;
using std::priority_queue;
const int MaxVexNum = 5002;
const int INF = 1000000000;
class Edge
{
public:
int to, capacity, flow;
Edge(int t, int c, int f)
{
to = t,capacity = c,flow = f;
}
};
vector<pair<int, int>>direction{ {0,-1},{0,1},{1,0},{-1,0} };
class Network
{
private:
int vexnum, edgenum, source, destination,maxflow;
vector<vector<Edge>>adjList;
public:
void addEdge(int from, int to, int cap)
{
adjList[from].push_back({ to, cap, (int)adjList[to].size() });
adjList[to].push_back({ from, 0, (int)adjList[from].size() - 1 });
}
Network()
{
adjList.resize(MaxVexNum);
int row, column; cin >> row >> column >> vexnum;
source = 0, destination = 2 * row*column + 1;
//链接source到银行处
for (int i = 0; i < vexnum; i++)
{
int x, y; cin >> x >> y;
auto first = (x - 1)*column + y, second = first + row*column;
addEdge(source, first, 1);
}
//拆点,连每个点的前后点
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= column; j++)
{
auto first = (i - 1)*column + j, second = first + row*column;
addEdge(first, second, 1);
for (int k = 0; k < 4; k++)
{
int x = i + direction[k].first, y = j + direction[k].second;
auto FIRST = (x - 1)*column + y, SECOND = FIRST + row*column;
if (x >= 1 && x <= row&&y>=1 && y <= column)
{
addEdge(second, FIRST,1);
}
}
if (i == 1 || i == row || j == 1 || j == column)
{
addEdge(second,destination,1);
}
}
}
}
int dfs(int src, int sink, int flow,vector<bool>&used)
{
if (src == sink)
{
return flow;
}
used[src] = true;
for (int i = 0; i<adjList[src].size(); i++)
{
Edge &edge = adjList[src][i];
if (!used[edge.to] && edge.capacity>0)
{
int minflow = dfs(edge.to, sink, std::min(flow, edge.capacity),used);
if (minflow>0)
{
edge.capacity -= minflow;
adjList[edge.to][edge.flow].capacity += minflow;
return minflow;
}
}
}
return 0;
}
void getMaxFlow()
{
maxflow = 0;
while (1)
{
vector<bool>used(MaxVexNum);
int f = dfs(source, destination, INF,used);
if (!f)
{
return;
}
maxflow += f;
}
}
void print()
{
if (vexnum == maxflow)
{
cout << "possible" << endl;
}
else
{
cout << "not possible" << endl;
}
}
};
int main()
{
//freopen("input.txt", "r", stdin);
//freopen("output.txt", "w", stdout);
int T; cin >> T;
while (T--)
{
Network network;
network.getMaxFlow();
network.print();
}
return 0;
}