poj2226Muddy Fields(二分图的最小点覆盖)

http://poj.org/problem?id=2226

模板抄错,结果错了一下午。将连续横行上的*和连续纵桁上点分别看做两个点集,连接两集合中点的边就是图中的点。即求最小顶点覆盖最多的边。最小点覆盖=最大匹配。

有篇图片的讲解,挺好,很形象。http://ip96cns.blog.163.com/blog/static/170095192201117465473/

View Code
 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 using namespace std;

 5 int map[1000][1000];

 6 int r,c,link[1000],vis[1000];

 7 int find(int x,int n)//二分匹配模板

 8 {

 9     int i,j;

10     for(i = 1; i <= n ; i++)

11     {

12         if(map[x][i]&&!vis[i])

13         {

14             vis[i] = 1;

15             if(link[i]==0||find(link[i],n))

16             {

17                 link[i] = x;

18                 return 1;

19             }

20         }

21     }

22     return 0;

23 }

24 int main()

25 {

26     int i,j,k,a[100][100],b[100][100];

27     char s[100][100];

28     while(cin>>r>>c)

29     {

30         memset(link,0,sizeof(link));

31 

32         memset(map,0,sizeof(map));

33         k = 0;

34         int sum = 0;

35         int ii=1,jj=1;

36         for(i = 1 ; i <= r ; i++)

37         {

38             getchar();

39             for(j = 1; j <= c ; j++)

40             {

41                 scanf("%c", &s[i][j]);

42             }

43         }

44         for(i = 1; i <= r ; i++)

45         for(j = 1; j <= c ; j++)//建立X集合中的点

46         {

47             if(j==1&&i!=1&&s[i-1][c]=='*')

48             ii++;

49             if(s[i][j]=='*')

50             {

51                 a[i][j] = ii;

52             }

53             if(j!=c&&(s[i][j]=='*'&&s[i][j+1]!='*'))

54                 ii++;

55         }

56         for(i = 1; i <= c ; i++)//建立Y集合中的点

57         for(j = 1; j <= r ; j++)

58         {

59             if((j==1&&i!=1&&s[r][i-1]=='*'))

60             jj++;

61             if(s[j][i]=='*')

62             b[j][i] = jj;

63             if(j!=r&&(s[j][i]=='*'&&s[j+1][i]!='*'))

64             {

65                 jj++;

66             }

67         }

68         for(i = 1; i <= r ; i++)

69         for(j = 1; j <= c ; j++)//建立连接两集合点的边,即图中的"*"

70         {

71             if(s[i][j]=='*')

72             {

73                 map[a[i][j]][b[i][j]] = 1;

74             }

75         }

76         for(i = 1; i <= ii ; i++)

77         {

78             memset(vis,0,sizeof(vis));

79             if(find(i,jj))//寻找最大匹配

80             {

81                 sum++;

82             }

83         }

84         cout<<sum<<endl;

85     }

86     return 0;

87 }

 

你可能感兴趣的:(Field)