1.树的最大独立集
对于一颗n结点的无根树,选出尽量多的结点,使得任何两个结点均不相邻,然后输入n-1条无向边,输出一个最大独立集。
#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
using namespace std;
#define maxn 100
vector<int> v[maxn];
int d[maxn], s[maxn], gs[maxn];
int dfs(int n, int fa)
{
for(int i = 0; i < v[n].size(); i++)
{
int m = v[n][i];
if(m != fa)dfs(m, n);
s[n] += d[m];
if(fa != -1)
gs[fa] += d[m];
}
d[n] = max(s[n], gs[n] + 1);
return d[n];
}
int main()
{
int n;
while(cin >> n)
{
for(int i = 0; i < n; i++)
v[i].clear();
for(int i = 0; i < n-1; i++)
{
int a, b;
cin >> a >> b;;
v[a].push_back(b);
v[b].push_back(a);
}
memset(d, 0, sizeof(d));
memset(s, 0, sizeof(s));
memset(gs, 0, sizeof(gs));
cout << dfs(i, -1) << endl;
}
return 0;
}
2.树的重心
对于一棵n个结点的无根树,找到一个点,使得把树变成以该结点为根的有根树时,最大子树结点数最小。
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
using namespace std;
const int maxn = 1000 + 10;
int d[maxn];
int minNode;
int minbt;
vector<int>tree[maxn];
int n;
int dfs(int node, int parent) {
d[node] = 1;
int u = 0;
for (int i = 0; i < tree[node].size(); i++) {
int son = tree[node][i];
if (son != parent) {
dfs(son, node);
d[node] += d[son];
u = max(u, d[son]);//找出node的最大子树节点个数
}
}
u = max(u, n - d[node]);//n-d[node]是parent的结点个数
if (u < minbt) {
minbt = u;
minNode = node;
}
}
int main()
{
int kase;
cin >> kase;
while (kase--) {
cin >> n;
for (int i = 0; i < n; i++) {
tree[i].clear();
}
for (int i = 0; i < n; i++) {
int u, v;
cin >> u >> v;
tree[u].push_back(v);
tree[v].push_back(u);
}
minNode = 0;
minbt = 100000000;
dfs(1, 0);
cout << minNode << " " << minbt << endl;
}
return 0;
}
3.树的最长路径
对于一棵n个结点的无根树,找到一条最长路径,就是找两个结点,使得它们之间距离最大
可以用dfs先求一个结点的最远结点v,然后再求v结点的最远结点u,u-v就是最长距离。
动态规划是更新结点的左右两端距离
#include<iostream>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<stdio.h>
#include<string>
#include<vector>
using namespace std;
const int maxn = 1000 + 10;
int d[maxn];
int first[maxn], second[maxn];
vector<int>tree[maxn];
int n;
int res;
void dfs(int node, int parent) {
d[node] = 0;
int u = 0;
for (int i = 0; i < tree[node].size(); i++) {
int son = tree[node][i];
if (son != parent) {
dfs(son, node);
if (first[son] + 1 >= first[node]) {//node结点的最长路径肯定不包括son的那枝子树
first[node] = first[son] + 1;//first存储最长的路径/
second[node] = first[node];//second存储次长的路径
}
else if(first[son]+1>second[node]){
second[node] = first[son] + 1;
}
}
}
res = max(res, first[node] + second[node]);
}
int main()
{
int kase;
cin >> kase;
while (kase--) {
cin >> n;
for (int i = 0; i < n; i++) {
tree[i].clear();
}
for (int i = 0; i < n; i++) {
int u, v;
cin >> u >> v;
tree[u].push_back(v);
tree[v].push_back(u);
}
dfs(1, 0);
cout << res << endl;
}
return 0;
}