poj 3041 二分图最小点集覆盖

定理:二分图的最大匹配=最小点覆盖。

思路:将所有行看做点集X,所有列看做点集Y,如果在[i, j]处有小行星,则建立一条从i到j的边,然后求最大匹配即为最小点覆盖数即为答案。

 1 #include <iostream>

 2 #include <cstring>

 3 #include <cstdio>

 4 using namespace std;

 5 

 6 const int N = 501;

 7 const int M = N * N;

 8 int head[N];

 9 int mark[N];

10 bool visit[N];

11 int n, m, e;

12 

13 void init()

14 {

15     e = 0;

16     memset( head, -1, sizeof(head) );

17 }

18 

19 struct Edge

20 {

21     int v, next;

22 } edge[M];

23 

24 void addEdge( int u, int v )

25 {

26     edge[e].v = v;

27     edge[e].next = head[u];

28     head[u] = e++;

29 }

30 

31 int dfs( int u )

32 {

33     for ( int i = head[u]; i != -1; i = edge[i].next )

34     {

35         int v = edge[i].v;

36         if ( !visit[v] )

37         {

38             visit[v] = 1;

39             if ( mark[v] == -1 || dfs( mark[v] ) )

40             {

41                 mark[v] = u;

42                 return 1;

43             }

44         }

45     }

46     return 0;

47 }

48 

49 int hungary()

50 {

51     memset( mark, -1, sizeof(mark) );

52     int res = 0;

53     for ( int i = 1; i <= n; i++ )

54     {

55         memset( visit, 0, sizeof(visit) );

56         res += dfs(i);

57     }

58     return res;

59 }

60 

61 int main ()

62 {

63     while ( scanf("%d%d", &n, &m) != EOF )

64     {

65         init();

66         while ( m-- )

67         {

68             int u, v;

69             scanf("%d%d", &u, &v);

70             addEdge( u, v );

71         }

72         int ans = hungary();

73         printf("%d\n", ans);

74     }

75     return 0;

76 }

 

你可能感兴趣的:(poj)