先写下几个术语,以后忘了就来找:

点覆盖集:点“看住”边。

点支配集:点“看住”点。

独立集:没有公共点的边 or 没有公共边的点。

这是我个人的理解,通俗就好。

两个结论:最小点支配集 == 全集 - 最大独立集; 二分图中,最小点覆盖集 == 最大二分匹配。

这题是求最小点覆盖集的,做这题时我才知道上面的结论,怎么证明我就不会了。

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define N 105
 4 #define E 1010
 5 int b[N],m,n;
 6 int fst[N],next[E],v[E];
 7 bool vis[N];
 8 bool find(int u)
 9 {
10     int e;
11     for(e = fst[u]; e != -1; e = next[e])
12     if(!vis[v[e]])
13     {
14         vis[v[e]] = 1;
15         if(b[v[e]] == -1 || find(b[v[e]]))
16         {
17             b[v[e]] = u;
18             return 1;
19         }
20     }
21     return 0;
22 }
23 int MaxMatch()
24 {
25     int i,cnt=0;
26     memset(b,-1,sizeof(b));
27     for(i = 1; i <= n; i++)
28     {
29         memset(vis,0,sizeof(vis));
30         if(find(i)) cnt++;
31     }
32     return cnt;
33 }
34 int main()
35 {
36     int k,i,u,t;
37     while(scanf("%d",&n),n)
38     {
39         scanf("%d%d",&m,&k);
40         memset(fst,-1,sizeof(fst));
41         for(i = 0; i < k; i++)
42         {
43             scanf("%*d%d%d",&u,&t);
44             if(!u || !t) continue;
45             next[i] = fst[u];
46             fst[u] = i;
47             v[i] = t;
48         }
49         printf("%d\n",MaxMatch());
50     }
51     return 0;
52 }

这里的代码比起上一篇就有优化了。