hdu 3360(最小覆盖)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3360
思路:最小覆盖==最大匹配。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<vector> 6 using namespace std; 7 #define MAXN 3333 8 vector<int>vet[MAXN]; 9 int map[MAXN][MAXN]; 10 int ly[MAXN]; 11 bool mark[MAXN]; 12 int n,m; 13 int dir[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}; 14 15 bool Judge(int x,int y){ 16 if(x>=1&&x<=n&&y>=1&&y<=m) 17 return true; 18 return false; 19 } 20 21 int dfs(int u) 22 { 23 for(int i=0;i<vet[u].size();i++){ 24 int v=vet[u][i]; 25 if(!mark[v]){ 26 mark[v]=true; 27 if(ly[v]==-1||dfs(ly[v])){ 28 ly[v]=u; 29 return 1; 30 } 31 } 32 } 33 return 0; 34 } 35 36 int MaxMatch() 37 { 38 int res=0; 39 memset(ly,-1,(n*m+2)*sizeof(int)); 40 for(int i=1;i<=n*m;i++){ 41 memset(mark,false,(n*m+2)*sizeof(mark[0])); 42 res+=dfs(i); 43 } 44 return res; 45 } 46 47 48 int main() 49 { 50 // freopen("1.txt","r",stdin); 51 int t=1; 52 while(scanf("%d%d",&n,&m),(n+m)){ 53 for(int i=1;i<=n*m;i++)vet[i].clear(); 54 for(int i=1;i<=n;i++) 55 for(int j=1;j<=m;j++) 56 scanf("%d",&map[i][j]); 57 for(int i=1;i<=n;i++) 58 { 59 for(int j=1;j<=m;j++) 60 { 61 if(map[i][j]!=-1){ 62 for(int k=0;k<12;k++){ 63 if((map[i][j]>>k)&1){ 64 int x=i+dir[k][0]; 65 int y=j+dir[k][1]; 66 if(Judge(x,y)&&map[x][y]!=-1){ 67 vet[(i-1)*m+j].push_back((x-1)*m+y); 68 vet[(x-1)*m+y].push_back((i-1)*m+j); 69 } 70 } 71 } 72 } 73 } 74 } 75 int ans=MaxMatch(); 76 printf("%d. %d\n",t++,ans/2); 77 } 78 return 0; 79 }