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

本文介绍如何利用最大匹配算法解决最小顶点覆盖问题,并通过实例演示了求解过程。文中提供了详细的代码实现步骤,包括输入数据处理、构建图、应用二分匹配模板等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 }

 

转载于:https://www.cnblogs.com/shangyu/archive/2013/01/18/2866673.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值