先写下几个术语,以后忘了就来找:
点覆盖集:点“看住”边。
点支配集:点“看住”点。
独立集:没有公共点的边 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 }
这里的代码比起上一篇就有优化了。