首页 > 代码库 > COGS746. [网络流24题] 骑士共存

COGS746. [网络流24题] 骑士共存

骑士共存问题
«问题描述:
在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示。棋盘

上某些方格设置了障碍,骑士不得进入。

技术分享

«编程任务:
对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑
士,使得它们彼此互不攻击。
«数据输入:
由文件knight.in给出输入数据。第一行有2 个正整数n 和m (1<=n<=200, 0<=m<=n*n)<n2),< span="">
分别表示棋盘的大小和障碍数。接下来的m 行给出障碍的位置。每行2 个正整数,表示障
碍的方格坐标。
«结果输出:
将计算出的共存骑士数输出到文件knight.out。
输入文件示例 输出文件示例
knight.in
3 2
1 1

3 3

knight.out

5

 

二分图最大独立集,转化为二分图最大匹配,从而用最大流解决。

 

  1 #include<iostream>  2 #include<cstdio>  3 #include<algorithm>  4 #include<cstring>  5 #include<queue>  6 #include<vector>  7 using namespace std;  8 const int mx[9]={0,1,1,-1,-1,2,2,-2,-2};  9 const int my[9]={0,2,-2,2,-2,1,-1,1,-1}; 10 const int mxn=42000; 11 int read(){ 12     int x=0,f=1;char ch=getchar(); 13     while(ch<0 || ch>9){if(ch==-)f=-1;ch=getchar();} 14     while(ch>=0 && ch<=9){x=x*10-0+ch;ch=getchar();} 15     return x*f; 16 } 17 struct edge{int v,nxt,f;}e[mxn<<4]; 18 int hd[mxn],mct=1; 19 void add_edge(int u,int v,int f){ 20     e[++mct].v=v;e[mct].f=f;e[mct].nxt=hd[u];hd[u]=mct;return; 21 } 22 int n,m; 23 int S,T; 24 int d[mxn]; 25 int id[210][210]; 26 int mp[210][210]; 27 bool BFS(int s,int t){ 28     queue<int>q; 29     memset(d,0,sizeof d); 30     d[s]=1; 31     q.push(s); 32     while(!q.empty()){ 33         int u=q.front();q.pop(); 34         for(int i=hd[u];i;i=e[i].nxt){ 35             int v=e[i].v; 36             if(!d[v] && e[i].f){ 37                 d[v]=d[u]+1; 38                 q.push(v); 39             } 40         } 41     } 42     return d[t]; 43 } 44 int DFS(int u,int lim){ 45     if(u==T)return lim; 46     int tmp,f=0; 47     for(int i=hd[u];i;i=e[i].nxt){ 48         int v=e[i].v; 49         if(d[v]==d[u]+1 && e[i].f){ 50             tmp=DFS(v,min(lim,e[i].f)); 51             e[i].f-=tmp; 52             e[i^1].f+=tmp; 53             lim-=tmp; 54             f+=tmp; 55             if(!lim)return f; 56         } 57     } 58     d[u]=0; 59     return f; 60 } 61 inline int Dinic(){ 62     int res=0; 63     while(BFS(S,T))res+=DFS(S,1e9); 64     return res; 65 } 66 void solve(){ 67     int i,j; 68     for(i=1;i<=n;i++) 69      for(j=1;j<=n;j++) 70          id[i][j]=(i-1)*n+j; 71     for(i=1;i<=n;i++) 72      for(j=1;j<=n;j++){ 73          if(mp[i][j])continue; 74          if((i+j)%2==0)//白色 75         { 76             add_edge(S,id[i][j],1); 77             add_edge(id[i][j],S,0);     78              for(int k=1;k<=8;k++){ 79                  int nx=i+mx[k],ny=j+my[k];  80                  if(nx<1 || nx>n || ny<1 || ny>n || mp[nx][ny])continue; 81                 add_edge(id[i][j],id[nx][ny],1); 82                  add_edge(id[nx][ny],id[i][j],0); 83              } 84         } 85         else{//黑色  86             add_edge(id[i][j],T,1); 87             add_edge(T,id[i][j],0); 88         } 89      } 90     return; 91 } 92 int main() 93 { 94     freopen("knight.in","r",stdin); 95     freopen("knight.out","w",stdout); 96     n=read();m=read(); 97     int i,j,u,v; 98     for(i=1;i<=m;i++){ 99         u=read();v=read();100         mp[u][v]=1;//标记障碍 101     }102     S=0;T=n*n+1;103     solve();104     105     int ans=Dinic();106     ans=n*n-m-ans;107     printf("%d\n",ans);108     return 0;109 }

 

COGS746. [网络流24题] 骑士共存