数和图的存储方式:
树是一种特殊的图 ,是无环连通图。
有向图的存储:
- 邻接矩阵 g[a,b] a和b的关系 权重 bool值
- 邻接表 有n个点 就开了n个单链表 每一个节点上开了一个单链表
每个单链表上存储的值是什么?
- 存储这个点可以走到哪个点。
- 单链表里面的顺序是无关紧要的,只要能表示此点可以到哪个点就可以。 二维数组,记录 ab ba,如果是无权重, 就是bool或者01表示。如果有权值就记录权值。
树图的遍历有两种方式:
- 深度优先遍历 一般的题目都是只遍历一次
- 宽度优先遍历 一般的题目都是只遍历一次
无向图也是一种特殊的有向图
考虑有向图如何遍历
树也是一种特殊的图
题目:
树的重心:
给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。
请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。
重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
输入格式: 第一行包含整数 n,表示树的结点数。 接下来 n−1 行,每行包含两个整数 a 和 b,表示点 a 和点 b 之间存在一条边。
输出格式: 输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。
代码如下:
#include<iostream>
#include<cstring>
using namespace std;
const int N=1e6+10;
int h[N],e[N],ne[N];
int idx;//记录每次的操作数
int n;//记录总的输入数
int ans=N;//记录答案
bool st[N];//记录 走过的点
void add(int a,int b)//单链表中的头插法 基操
{
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
int bfs(int u)返回以此点为根节点的树的大小
{
st[u]=true;
int sum=1; int res=0;
//sum指以此点为根节点的树的大小 res指删除此点后剩余连通块中 树的最大值
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];//只遍历图每个点一次
if(!st[j])
{
int s=bfs(j);
res=max(res,s);//比较此点以下的连通块的大小
sum+=s;//sum指的是一次点为根节点的树的大小因此要加上子树的大小
}
}
res=max(res,n-sum);//和此点上面的连通块比较
ans=min(ans,res);//全局的 比较 从而找出树的重心
return sum;
}
int main()
{
memset(h,-1,sizeof h);
cin>>n;
int a,b;
for(int i=1;i<n;i++)
{
cin>>a>>b;
add(a,b); add(b,a);
}
bfs(1);
cout<<ans<<endl;
return 0;
}
此算法的学习来自网站 acwing
y总的方法是在秒的一批
推荐学习。