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 }

 

posted @ 2014-03-30 11:42  辛力啤  阅读(171)  评论(0编辑  收藏  举报