HDU 1498 -- 二分图的最大匹配

本文介绍了一种基于消除游戏的算法实现方案,通过枚举不同颜色并利用最大匹配原理找到不可在规定时间内消除的颜色组合。使用C++代码示例展示了如何构建匹配图并计算最小覆盖点数。

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

考察:枚举,最小覆盖点数 = 最大匹配。

思路:枚举每一种颜色,如果该颜色的最小覆盖点大于规定时间K,说明不能够在时间内消除完,即为答案。因为在单位时间里可以消除一行或者一列中相同的颜色,建图的时候,将每个点的横坐标去匹配其纵坐标即可(既完成了消除整行或者整列的目的)。由于题目要求将结果从小到大输出,那么可以用STL里的set来完成枚举并自动排序。

 

View Code
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <set>
 5 #define MAX 105
 6 
 7 using namespace std;
 8 
 9 set<int> S;
10 set<int>::iterator iter;
11 bool cnt[MAX][MAX];
12 int link[MAX];
13 bool used[MAX];
14 int map[MAX][MAX];
15 int ans[MAX];
16 int N,K,index;
17 
18 bool dfs(int left)
19 {
20     for(int i=1;i<=N;i++)
21     {
22         if(cnt[left][i] && !used[i])
23         {
24             used[i]=true;
25             if(link[i]==-1 || dfs(link[i]))
26             {
27                 link[i]=left;
28                 return true;
29             }
30         }
31     }
32     return false;
33 }
34 
35 int Match()
36 {
37     memset(link,-1,sizeof(link));
38     int ret=0;
39     for(int i=1;i<=N;i++)
40     {
41         memset(used,0,sizeof(used));
42         if(dfs(i))
43             ret ++;
44     }
45     return ret;
46 }
47 
48 int main()
49 {
50     while(~scanf("%d%d",&N,&K))
51     {
52         if(!N && !K)
53             break;
54         S.clear();
55         index=0;
56         for(int i=1;i<=N;i++)
57         {
58             for(int j=1;j<=N;j++)
59             {
60                 scanf("%d",&map[i][j]);
61                 S.insert(map[i][j]);
62             }
63         }
64         for(iter=S.begin();iter!=S.end();iter++)
65         {
66             for(int i=1;i<=N;i++)
67             {
68                 for(int j=1;j<=N;j++)
69                 {
70                     if(map[i][j]==(*iter))
71                         cnt[i][j]=true;
72                     else
73                         cnt[i][j]=false;
74                 }
75             }
76             int temp=Match();
77             if(temp>K)
78                 ans[index++]=(*iter);
79         }
80         if(index==0)
81             printf("-1\n");
82         else
83         {
84             for(int i=0;i<index;i++)
85             {
86                 printf("%d",ans[i]);
87                 if(i!=index-1)
88                     printf(" ");
89             }
90             printf("\n");
91         }
92     }
93     return 0;
94 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值