hdu 3360 National Treasures http://acm.hdu.edu.cn/showproblem.php?pid=3360 2013-2-3
最少的保安数=n*m-最多的物品数
最多的物品数就是最大独立集 物品的奇偶不同才可能有边 是二分图
View Code
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 using namespace std; 5 6 const int N=2600; 7 struct BGMatch{ 8 int n; 9 vector<int> G[N]; 10 int mat[N]; 11 bool vis[N]; 12 void init(int tn){ 13 n=tn; 14 for(int i=0;i<n;i++) G[i].clear(); 15 } 16 void addMatch(int u,int v){ 17 G[u].push_back(v); 18 } 19 bool find(int u){ 20 int sz=G[u].size(); 21 for(int i=0;i<sz;i++){ 22 int v=G[u][i]; 23 if(vis[v]) continue; 24 vis[v]=true; 25 if(mat[v]==-1 || find(mat[v])){ 26 mat[v]=u; 27 return true; 28 } 29 } 30 return false; 31 } 32 int maxMatch(){ 33 int cnt=0; 34 memset(mat,-1,sizeof(mat)); 35 for(int u=0;u<n;u++){ 36 memset(vis,0,sizeof(vis)); 37 if(find(u)) cnt++; 38 } 39 return cnt; 40 } 41 }; 42 43 BGMatch g; 44 const int dx[]={-1,-2,-2,-1,1,2,2,1,-1,0,1,0}; 45 const int dy[]={-2,-1,1,2,2,1,-1,-2,0,1,0,-1}; 46 int mz[55][55]; 47 int main(){ 48 int n,m,C=0; 49 while(scanf("%d%d",&n,&m),n||m){ 50 g.init(n*m); 51 for(int i=0;i<n;i++) 52 for(int j=0;j<m;j++) scanf("%d",&mz[i][j]); 53 for(int x=0;x<n;x++) 54 for(int y=0;y<m;y++) if(mz[x][y]!=-1){ 55 int t=mz[x][y]; 56 for(int i=0;i<12;i++) if((t>>i)&1){ 57 int nx=x+dx[i], ny=y+dy[i]; 58 if(nx>=0 && nx<n && ny>=0 && ny<m && mz[nx][ny]!=-1){ 59 g.addMatch(x*m+y,nx*m+ny); 60 g.addMatch(nx*m+ny,x*m+y); 61 } 62 } 63 } 64 int ans=g.maxMatch()/2; 65 printf("%d. %d\n",++C,ans); 66 } 67 return 0; 68 }