题意:曹操在一个area上,孙刘联军为了防止曹操逃跑就必须设法堵住他的所有逃跑去路,即不能达到area的边缘。
构图的方法就是:
1.设置一个额外源点与所有边界点相连 , 一个额外汇点与所有0相连 ,由于对于所有-1我们可以看成是需要0的时间去毁掉它 , 所以可以直接将其忽略。
2.每个非零点与其相邻4个非零顶点相连建立无向边 , 向零点连有向边 。
3.将点拆成边,零边赋为infinty, 非零点赋值为该点值 ,之后直接求最小割即可。
#include <cstdio> #include <cstring> const int maxn=1850; const int inf=1<<29; const int s=0;//source struct edge{ int v,next,w; }edge[maxn*8]; int head[maxn],cnt;//for sap void addedge(int u, int v, int w) { edge[cnt].v=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].w=0; edge[cnt].next=head[v]; head[v]=cnt++; } int sap(int t) { int pre[maxn],cur[maxn],dis[maxn],gap[maxn]; int flow=0 , aug=inf ,u; bool flag; for (int i=0 ; i<=t ; ++i) { cur[i]=head[i]; gap[i]=dis[i]=0; } gap[s]=t+1; u=pre[s]=s; while (dis[s]<=t) { flag=0 ; for (int &j=cur[u] ; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[u]==dis[v]+1) { flag=1; if(edge[j].w<aug)aug=edge[j].w; pre[v]=u; u=v; if (u==t) { flow+=aug; //printf("%d %d \n", flow , aug ); while (u!=s) { u=pre[u]; edge[cur[u]].w-=aug; edge[cur[u]^1].w+=aug; } aug=inf; } break; } } if (flag)continue ; int mindis=t+1; for (int j=head[u]; ~j ; j=edge[j].next) { int v=edge[j].v; if (edge[j].w>0 && dis[v]<mindis) { mindis=dis[v]; cur[u]=j; } } if(--gap[dis[u]]==0)break; gap[dis[u]=mindis+1]++; u=pre[u]; } return flow; } int r,c,map[35][35];//for init int dir[4][2]={0,1 , 1,0 , -1,0 , 0,-1}; void build_graph() { int i,j; int num=r*c; for (int i=0 ; i<r ; ++i) { for (int j=0 ; j<c ; ++j) { if(map[i][j]==-1)continue; if(i==0 || j==0 || i==r-1 || j==c-1)//map if on the edge of the area { if(~map[i][j])addedge(0 , i*c+j+1 , inf); //addedge (i*r+j+1 , i*r+j+1+r*c , map[i][j]); } else if(!map[i][j])//map is 0 { addedge(i*c+j+1+r*c , r*c*2+1 , inf); addedge(i*c+j+1 , r*c+i*c+j+1 , inf); } if(map[i][j]) { for (int k=0 ; k<4 ; ++k) { int x=i+dir[k][0],y=j+dir[k][1]; if(x<0 || y<0 || x>=r || y>=c)continue ; if(!map[x][y])addedge(i*c+j+1+r*c , x*c+y+1 , inf); else addedge(x*c+y+1+r*c , i*c+j+1 , inf), addedge(i*c+j+1+r*c , x*c+y+1 , inf); } addedge(i*c+j+1,i*c+j+1+r*c,map[i][j]); } } } } void init () { memset (head , -1 , sizeof(head)); cnt=0; } int main () { int cas; scanf("%d",&cas); while (cas--) { init(); scanf("%d%d",&r,&c); for (int i=0 ; i<r ; ++i) for (int j=0 ; j<c ; ++j) { scanf("%d",(*(map+i)+j)); } build_graph(); printf("%d\n",sap(r*c*2+1)); } return 0; }