http://www.lydsy.com/JudgeOnline/problem.php?id=4808
题意:
思路:
这图中的两个马只能选一个,二选一,很像二分图吧,对能互吃的两个棋子连线,在所选的任意两个棋子中,都不能互相有连线,这不就是最大点独立集吗?
最大独立集 = 顶点个数 - 最大匹配。记得把坏了的格子去掉。
1 #include2 #include 3 #include 4 using namespace std; 5 6 int n,m,tot; 7 int mp[205][205], head[40005], mark[40005]; 8 bool vis[40005]; 9 10 struct node 11 { 12 int v,next; 13 }e[8*40005]; 14 15 int dx[] = {-2,-2,-1,-1,1,1,2,2}; 16 int dy[] = {1,-1,2,-2,2,-2,1,-1}; 17 18 void addEdge(int u, int v) 19 { 20 e[tot].v = v; 21 e[tot].next = head[u]; 22 head[u] = tot++; 23 } 24 25 bool match(int u) 26 { 27 for(int i=head[u];i!=-1;i=e[i].next) 28 { 29 int v = e[i].v; 30 if(!vis[v]) 31 { 32 vis[v] = true; 33 if(mark[v]==-1 || match(mark[v])) 34 { 35 mark[v] = u; 36 return true; 37 } 38 } 39 } 40 return false; 41 } 42 43 int main() 44 { 45 //freopen("in.txt","r",stdin); 46 int num = 0; 47 scanf("%d%d",&n,&m); 48 for(int i=1;i<=n;i++) 49 for(int j=1;j<=m;j++) 50 { 51 scanf("%d",&mp[i][j]); 52 if(mp[i][j]) num++; 53 } 54 tot = 0; 55 memset(head,-1,sizeof(head)); 56 for(int i=1;i<=n;i++) 57 for(int j=1;j<=m;j++) 58 { 59 if(!mp[i][j]) 60 { 61 for(int k=0;k<8;k++) 62 { 63 int x = i+dx[k]; 64 int y = j+dy[k]; 65 if(x<1 || x>n || y<1 || y>m) continue; 66 if(mp[x][y]==1) continue; 67 int p1 = (i-1)*m+j; 68 int p2 = (x-1)*m+y; 69 addEdge(p1,p2); 70 } 71 } 72 } 73 int sum = 0; 74 memset(mark,-1,sizeof(mark)); 75 for(int i=1;i<=n*m;i++) 76 { 77 memset(vis,false,sizeof(vis)); 78 if(match(i)) sum++; 79 } 80 printf("%d\n",n*m-num-sum/2); 81 return 0; 82 }