这题有很多第一次
第一次用了数组表示的邻接表 以前都是用vector
第一次学了拆点 参考大神的 最大流建图是重点
题意看图 就是所有点要到边界 不能转弯超过一次 不能重叠
第一次不懂什么是拆点 看了下这个就懂了 说的蛮好的
http://www.cnblogs.com/scau20110726/archive/2012/12/20/2827177.html
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX = 30010;
const int MAXN = 5010;
struct edge
{
int u;
int v;
int next;
int flow;
int cap;
}e[MAX];
int dir[4][2] = {1,0,-1,0,0,1,0,-1};
int first[MAXN];
int p[MAXN];
int a[MAXN];
int edgenum;
int n,m,num;
int s,t,f;
void add(int u,int v)
{
e[edgenum].u = u;
e[edgenum].v = v;
e[edgenum].flow = 0;
e[edgenum].cap = 1;
e[edgenum].next = first[u];
first[u] = edgenum++;
e[edgenum].u = v;
e[edgenum].v = u;
e[edgenum].flow = 0;
e[edgenum].cap = 0;
e[edgenum].next = first[v];
first[v] = edgenum++;
}
void EK()
{
queue <int> q;
f = 0;
while(1)
{
memset(a,0,sizeof(a));
memset(p,-1,sizeof(p));
a[0] = 999999999;
q.push(0);
while(!q.empty())
{
int u = q.front();
q.pop();
for(int k = first[u]; k != -1; k = e[k].next)
{
int v = e[k].v;
if(!a[v] && e[k].cap > e[k].flow)
{
p[v] = k;
q.push(v);
a[v] = min(a[u],e[k].cap - e[k].flow);
}
}
}
if(a[t] == 0)
break;
for(int k = p[t]; k != -1; k = p[e[k].u])
{
e[k].flow += a[t];
e[k^1].flow -= a[t];
}
f += a[t];
}
}
void init()
{
int i,j,k;
memset(first,-1,sizeof(first));
edgenum = 0;
for(i = 1; i <= n; i++)
{
for(j = 1; j <= m; j++)
{
int u = (i - 1) * m + j;
int e = u + n * m;
add(u,e);
for(k = 0; k < 4; k++)
{
int x = i + dir[k][0];
int y = j + dir[k][1];
if(x >= 1 && x <= n && y >= 1 && y <= m)
{
int uu = (x - 1) * m + y;
add(e,uu);
}
else
add(e,t);
}
}
}
for(i = 1; i <= num; i++)
{
scanf("%d %d",&j,&k);
add(s,(j - 1) * m + k);
}
}
int main()
{
int cas,i;
scanf("%d",&cas);
while(cas--)
{
scanf("%d %d %d",&n,&m,&num);
s = 0;
t = n * m * 2 + 1;
init();
EK();
if(f == num)
puts("possible");
else
puts("not possible");
}
return 0;
}