hdu 2119 最小点覆盖
1 /* 2 题意:给出一个由0和1组成的n*m的矩阵,每一次可以删除整行或者整列的1,问最少进行多少次删除可以将所有的1删除 3 4 题解:最小点覆盖==最大匹配 5 关键是建图:以行号为一个点集,列号为另一点集,矩阵中为1的方格加边(i,j),建立二部图(实际上不一定要以二部图 6 的思路来想,可以首先只是普通的一个建图,由行点集和列点集混合组成,然后在(i,j)加边,最后求这个图的最小点覆 7 盖,只是可以将两个点集分开排列就形成了二部图) 8 */ 9 #include <cstdio> 10 #include <cstring> 11 12 #define clr(a,b) (memset(a,b,sizeof(a))) 13 14 const int N = 105; 15 16 struct edge 17 { 18 int v,next; 19 }E[N*N]; 20 21 int EN; 22 23 int mat[N],head[N]; 24 bool vis[N]; 25 int n; 26 27 void insert(int u, int v) 28 { 29 E[EN].v = v; 30 E[EN].next = head[u]; 31 head[u] = EN++; 32 } 33 34 bool find(int t) 35 { 36 int v; 37 for(int i = head[t];i != -1 ;i = E[i].next) { 38 if(vis[ v = E[i].v ]) 39 continue; 40 vis[v] = true; 41 if(mat[v] == -1 || find(mat[v])) { 42 mat[v] = t; 43 return true; 44 } 45 } 46 return false; 47 } 48 inline int MaxMatch() { 49 int i,num = 0; 50 clr(mat,-1); 51 for(i = 0;i < n;i ++) { 52 clr(vis,false); 53 num += find(i); 54 } 55 return num; 56 } 57 58 int main(void) 59 { 60 int m; 61 while (~scanf("%d",&n) && n) 62 { 63 scanf("%d",&m); 64 EN = 0; 65 memset(head,-1,sizeof(head)); 66 for(int i=0; i<n; i++) 67 for(int j=0; j<m; j++) 68 { 69 int t; 70 scanf("%d",&t); 71 if (t) 72 { 73 insert(i,j); 74 } 75 } 76 printf("%d\n",MaxMatch()); 77 } 78 return 0; 79 }