这题有很多第一次
第一次用了数组表示的邻接表 以前都是用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; }