当前位置:网站首页>信息学奥赛一本通 1362:家庭问题(family)
信息学奥赛一本通 1362:家庭问题(family)
2022-06-30 19:48:00 【君义_noip】
【题目链接】
【题目考点】
1. 图论 图的遍历
3. 并查集
【解题思路】
本题按照原意直接理解当然也能做。如果用图论这一数据结构来辅助理解,结合图论中的定义,可以理解到这个问题的本质。
每个人是一个顶点,任何人之间的关系是边,所有的人和关系构成一个图,一个家庭就是一个连通分量。
求家庭个数就是求连通分量的个数,最大家庭人数就是所有连通分量中顶点数量最多的连通分量的顶点数。
可以在图上用搜索(深搜/广搜)来确定连通分量的数量。也可以使用并查集来完成。
(连通块本质上也是图上的连通分量,该题做法和求连通块问题类似)
解法1:搜索
从每个顶点尝试开始搜索,如果成功开始进行一次搜索,即可标记整个连通分量。成功开始搜索的次数即为连通分量的个数。搜索过程中对这一趟搜索到的顶点做计数,能达到在最大计数即为顶点数量最多的连通分量的顶点数。
解法2:并查集
将有关系的人加入一个集合。如果i与j有关系,那么把i所在的集合与j所在的集合合并,合并后的集合的元素个数为原来两集合元素个数的加和。最后统计集合数量,以及查找得到元素个数最大的集合的元素个数。
【题解代码】
解法1:搜索
- 深搜+邻接表
#include <bits/stdc++.h>
using namespace std;
#define N 105
vector<int> edge[N];//邻接表
int n, m, num, mx, ct;//num:连通分量数 ct:当前连通分量中的顶点数 mx:最大顶点数
bool vis[N];//vis[i]:顶点i是否已访问过
void init()//生成图
{
int f, t;
cin >> n >> m;
for(int i = 1; i <= m; ++i)
{
cin >> f >> t;
edge[f].push_back(t);
edge[t].push_back(f);
}
}
void dfs(int u)
{
for(int i = 0; i < edge[u].size(); ++i)
{
int v = edge[u][i];
if(vis[v] == false)
{
ct++;
vis[v] = true;
dfs(v);
}
}
}
int main()
{
init();
for(int i = 1; i <= n; ++i)
{
if(vis[i] == false)
{
num++;
ct = 1;
vis[i] = true;
dfs(i);
mx = max(mx, ct);//更新最大顶点数
}
}
cout << num << ' ' << mx;
return 0;
}
- 广搜+邻接矩阵
#include <bits/stdc++.h>
using namespace std;
#define N 105
bool edge[N][N];//邻接矩阵
int n, m, num, mx, ct;//num:连通分量数 ct:当前连通分量中的顶点数 mx:最大顶点数
bool vis[N];//vis[i]:顶点i是否已访问过
void init()
{
int f, t;
cin >> n >> m;
for(int i = 1; i <= m; ++i)
{
cin >> f >> t;
edge[f][t] = edge[t][f] = true;
}
}
void bfs(int v)//从顶点v开始广搜
{
queue<int> que;
vis[v] = true;
ct++;
que.push(v);
while(que.empty() == false)
{
int u = que.front();
que.pop();
for(int i = 1; i <= n; ++i)
{
if(edge[u][i] && vis[i] == false)
{
ct++;
vis[i] = true;
que.push(i);
}
}
}
}
int main()
{
init();
for(int i = 1; i <= n; ++i)
{
if(vis[i] == false)
{
num++;
ct = 0;
bfs(i);
mx = max(mx, ct);//更新最大顶点数
}
}
cout << num << ' ' << mx;
return 0;
}
3. 并查集
#include<bits/stdc++.h>
using namespace std;
#define N 105
int fa[N], n, m;
int ct[N];//ct[i]:以i为根结点的树的结点数量
void init(int n)
{
for(int i = 1; i <= n; ++i)
{
fa[i] = i;
ct[i] = 1;
}
}
int find(int x)
{
if(x == fa[x])
return x;
else
return fa[x] = find(fa[x]);
}
void merge(int i, int j)//合并i结点和j结点所在的集合
{
int x = find(i), y = find(j);
fa[x] = y;//x的父结点设为y
if(x != y)
ct[y] += ct[x];//以y为根节点的集合的顶点数ct[y]增加ct[x]
}
int main()
{
int f, t, num = 0, mx = 0;
cin >> n >> m;
init(n);
while(m--)
{
cin >> f >> t;
merge(f, t);
}
for(int i = 1; i <= n; ++i)
{
if(find(i) == i)//i是根结点
{
num++;//根结点的数量即为集合的数量
mx = max(ct[i], mx);//更新集合元素数量的最大值
}
}
cout << num << ' ' << mx;
return 0;
}
边栏推荐
猜你喜欢

项目经理是领导吗?可以批评指责成员吗?

消灭Bug,开发者不可不知的几款Bug探索测试神器。

QQmlApplicationEngine failed to load component qrc:/main.qml:-1 No such file or directory

Why should offline stores do new retail?

太湖 “中国健康农产品·手机直播万里行”走进太湖

Tensorflow2.4实现RepVGG
![Network planning | [five transport layers and six application layers] knowledge points and examples](/img/4f/31acce51b584bed5ef56b2093c4db3.png)
Network planning | [five transport layers and six application layers] knowledge points and examples

How to pass the PMP Exam quickly?
Django上传excel表格并将数据写入数据库的详细步骤
MySQL数据库误删回滚的解决
随机推荐
matlab 将三角剖分结果保存为STL文件
KubeVela 1.4:让应用交付更安全、上手更简单、过程更透明
消灭Bug,开发者不可不知的几款Bug探索测试神器。
composer
GeoServer installation
将秒数转换为**小时**分钟
新出生的机器狗,打滚1小时后自己掌握走路,吴恩达开山大弟子最新成果
Playwright - 滚动条操作
Unity 如何拖拉多个组件中的一个
This morning, investors began to travel collectively
neo4j load csv 配置和使用
Lombok
Application of JDBC in performance test
微信小程序开发实战 云音乐
Solution to rollback of MySQL database by mistake deletion
启动PHP报错ERROR: [pool www] cannot get uid for user ‘@[email protected]’
Exness: liquidity series - liquidity cleaning and reversal, decision interval
8 - function
Detailed steps for Django to upload excel tables and write data to the database
qt中toLocal8Bit和toUtf8()有什么区别