Question:
There are some artworks on R * C .. each artwork uses a non-negative number to indicate the grids near him that need security guards... -1 indicates that the grid is already a security guard .. ensure that security is essential to the key position of the art. or stop this art .. station security guard on this artwork .. ask the minimum number of security guards to meet the conditions...
Question:
Edge building based on the security conditions required for each piece of art .. note .. this edge means two points need to be connected .. so it is one thing that art points to security guards and security guards to art... the problem is transformed into the minimum point coverage problem of the Bipartite Graph (covering all edges with the least points .. edge is the security relationship needed .. point is the number of security guards to be added )... it is equivalent to finding its maximum match... note .. there are two ways to create a graph .. one is the parity point .. built on different points on both sides .. the answer is to run the maximum match .. the second is that both sides are the same points .. edge is also a bidirectional edge .. the answer is the maximum match/2.
Program:
#include<iostream>#include<stdio.h>#include<algorithm>#include<cmath>#include<stack>#include<string.h>#include<queue>#define ll long long#define esp 1e-5#define MAXN 3005#define MAXM 500005#define oo 100000007using namespace std; struct node{ int y,next;}line[MAXM];int match[MAXN],way[12][2]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};int Lnum,_next[MAXN],arc[MAXN][MAXN];bool used[MAXN];void addline(int x,int y){ line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y;}bool dfs(int x){ for (int k=_next[x];k;k=line[k].next) { int y=line[k].y; if (used[y]) continue; used[y]=true; if (!match[y] || dfs(match[y])) { match[y]=x; return true; } } return false;}int getmax(int n){ int sum=0; memset(match,0,sizeof(match)); for (int i=0;i<n;i++) { memset(used,false,sizeof(used)); sum+=dfs(i); } return sum;}int main(){ int i,cases=0,R,C,x,y,h; freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); while (~scanf("%d%d",&R,&C) && R) { for (y=0;y<R;y++) for (x=0;x<C;x++) scanf("%d",&arc[y][x]); Lnum=0,memset(_next,0,sizeof(_next)); for (y=0;y<R;y++) for (x=0;x<C;x++) if (arc[y][x]>0) { h=arc[y][x]; for (i=0;i<12;i++) if (h&(1<<i)) { int yy=y+way[i][0],xx=x+way[i][1]; if (xx<0 || yy<0 || xx>=C || yy>=R || arc[yy][xx]<0) continue; addline(y*C+x,yy*C+xx),addline(yy*C+xx,y*C+x); } } printf("%d. %d\n",++cases,getmax(R*C)/2); } return 0; } /*3 40 0 512 0536 512 0 00 0 512 03 40 0 0 0512 536 0 00 0 0 00 031*/