Code: Select all
#include <cstdio>
#include <cstring>
using namespace std;
const int MAX_ROW = 50;
const int MAX_VERTEX = MAX_ROW * MAX_ROW * 2 + 2;
struct Bank {
int x;
int y;
};
struct Edge {
int from;
int to;
int weight;
Edge* next;
};
Edge* g_map[MAX_VERTEX];
Bank g_bank[MAX_ROW * MAX_ROW];
int g_bankCount;
int g_rowCount, g_colCount;
int g_source, g_sink;
int g_path[MAX_VERTEX];
int headx(int x, int y) {
return (x * g_rowCount + y) * 2 + 1;
}
int tailx(int x, int y) {
return headx(x, y) + 1;
}
void addedge(int from, int to, int weight) {
Edge* newedge = new Edge;
newedge->from = from;
newedge->to = to;
newedge->weight = weight;
newedge->next = g_map[from];
g_map[from] = newedge;
}
void addweight(int from, int to, int weight) {
Edge* ptr = g_map[from];
while(ptr != NULL){
if(ptr->to == to) {
ptr->weight += weight;
return;
}
ptr = ptr->next;
}
/*if there is no connection between these*/
addedge(from, to, weight);
}
void clear_map() {
for (int i = 0; i < MAX_VERTEX; i++) {
Edge* p = g_map[i];
while (p != NULL) {
Edge* pre = p;
p = p->next;
delete pre;
}
g_map[i] = NULL;
}
}
void make_graph() {
clear_map();
g_source = 0;
g_sink = g_rowCount * g_colCount * 2 + 1;
for(int i = 0; i < g_rowCount; i++) {
for(int j = 0; j < g_colCount; j++) {
addedge(headx(i, j), tailx(i, j), 1);
}
}
for(int i = 1; i < g_rowCount; i++) {
for(int j = 0; j < g_colCount; j++) {
addedge(tailx(i - 1, j), headx(i, j), 1);
addedge(tailx(i, j), headx(i - 1, j), 1);
}
}
for(int i = 0; i < g_rowCount; i++) {
for(int j = 1; j < g_colCount; j++){
addedge(tailx(i, j - 1), headx(i, j), 1);
addedge(tailx(i, j), headx(i, j - 1), 1);
}
}
for(int i = 0; i < g_bankCount; i++) {
addedge(g_source, headx(g_bank[i].x, g_bank[i].y), 1);
}
for(int i = 0; i < g_rowCount; i++){
addedge(tailx(i, 0), g_sink, 1);
addedge(tailx(i, g_colCount - 1), g_sink, 1);
}
for(int i = 1; i < g_colCount - 1; i++) {
addedge(tailx(0, i), g_sink, 1);
addedge(tailx(g_rowCount - 1, i), g_sink, 1);
}
}
int bfs() {
int queue[MAX_VERTEX], parent[MAX_VERTEX], visited[MAX_VERTEX];
int front=0, tail=1,;
Edge* ptr;
memset(visited, 0, sizeof(visited));
queue[front] = g_source;
parent[front] = -1;
visited[g_source] = 1;
while(front < tail){
int now = queue[front];
for(ptr = g_map[now]; ptr != NULL; ptr = ptr->next) {
if(ptr->weight <= 0) {
continue;
}
if(visited[ptr->to]) {
continue;
}
parent[tail] = front;
queue[tail] = ptr->to;
visited[ptr->to] = 1;
if(ptr->to == g_sink) {
goto FIND_PATH;
}
tail++;
}
front++;
}
return 0;
FIND_PATH:
int result = -1;
for(int i = tail; i >= 0; i = parent[i]) {
result++;
g_path[result] = queue[i];
}
return result;
}
void maxflow() {
int flow = 0;
int len = bfs();
while (len > 0) {
/*reverse*/
for(int i = 1;i < len; i++) {
addweight(g_path[i], g_path[i - 1], -1);
addweight(g_path[i - 1], g_path[i], 1);
}
flow++;
len = bfs();
}
if(flow == g_bankCount) {
printf("possible\n");
}
else {
printf("not possible\n");
}
}
int main() {
memset(g_map, 0, sizeof(g_map));
int N;
scanf("%d", &N);
while (N > 0) {
scanf("%d %d %d", &g_rowCount, &g_colCount, &g_bankCount);
for(int i = 0; i < g_bankCount; i++) {
scanf("%d %d", &g_bank[i].x, &g_bank[i].y);
g_bank[i].x--;
g_bank[i].y--;
}
make_graph();
maxflow();
N--;
}
return 0;
}