树的重心(DFS)

#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
using namespace std;
const int maxn=1e5+10;
vector<int>v[maxn];
int subtree[maxn];//表示每点除去自身所对应的子树大小
bool vis[maxn];//用以标记,去重
int n;
void dfs(int father,int node)//father记录node上一步路径来源
{
  for(int i = 0 ; i < v[node].size() ; i++){
  int son=v[node][i];//son为下一步路径方向
  if(son == father){//避开node对应的父亲节点
    continue;
  }
  dfs(node,son);
  if(vis[son] == true)   continue ;//走过son路径
  subtree[node]+=subtree[son];//统计除去node本身的子树大小
  vis[node]=true;//标记
  }
  subtree[node]=max(subtree[node],n-subtree[node]);//去除node节点,保存两棵子树中的最大值
}
int main(){
  memset(subtree,0,sizeof(subtree));
  memset(vis,false,sizeof(vis));
  cin >> n;
  int a,b;
  for(int i = 1 ; i <= n-1 ; i++){
    cin >> a >> b;
    v[a].push_back(b);//无向树
    v[b].push_back(a);
  }
  dfs(0,1);//任意一点开始dfs,1号节点没有父亲,因而father为0
  int res=maxn;int node=0;
  for(int i = 1 ; i <= n; i++){//求出子树最大规模的最小值
    if(subtree[i] < res){
      res=subtree[i];
      node=i;
    }
  }
  cout << node << " " << res << endl;
  return 0;
}

原文地址:https://www.cnblogs.com/ecustlegendn324/p/11987399.html

时间: 2024-11-02 10:50:04

树的重心(DFS)的相关文章

Codeforces 686 D.Kay and Snowflake (dfs 树的重心)

题目链接: http://codeforces.com/problemset/problem/685/B 题意: 给你n个点,以1为根,然后给你2-n的节点的父亲节点编号.问你每一颗子树的重心是哪一个节点. 思路: 有定理:把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上. 考虑树的重心在哪个部分,一定是在当前节点u的最大子树v中,假设我们已经知道了子树v的重心ans[v],那么u的重心呢?就是在ans[v]这个节点到u的路径上. 代码: #include<b

poj1655 Balancing Act 求树的重心

http://poj.org/problem?id=1655 Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9072   Accepted: 3765 Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a fo

POJ1655 Balancing Act(树的重心)

题目链接 Balancing Act 就是求一棵树的重心,然后统计答案. 1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define REP(i,n) for(int i(0); i < (n); ++i) 6 #define for_edge(i,x) for(int i = H[x]; i; i = X[i]) 7 8 const int INF = 1 << 30; 9 const int N = 10

51nod 配对(求树的重心)

传送门:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1737 给出一棵n个点的树,将这n个点两两配对,求所有可行的方案中配对两点间的距离的总和最大为多少. Input 一个数n(1<=n<=100,000,n保证为偶数) 接下来n-1行每行三个数x,y,z表示有一条长度为z的边连接x和y(0<=z<=1,000,000,000) Output 一个数表示答案 Input示例 6 1 2 1 1 3 1

POJ 1655 Balancing Act (求树的重心)

求树的重心,直接当模板吧.先看POJ题目就知道重心什么意思了... 重心:删除该节点后最大连通块的节点数目最小 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<queue> 5 #include<stack> 6 using namespace std; 7 #define LL long long 8 #define clc(a,b) memset(a

POJ 1655 Balancing Act (树的重心,常规)

题意:求树的重心,若有多个重心,则输出编号较小者,及其子树中节点最多的数量. 思路: 树的重心:指的是一个点v,在删除点v后,其子树的节点数分别为:u1,u2....,设max(v)为其中的最大值,点v的max(v)是所有点里面最小的,称v为树的重心. 如何求任一重心?按树形来看,max(v)可以由其父亲贡献,也可以由其任一孩子贡献.孩子比较好解决,不就是深搜一遍,然后回溯时统计下数量就行了?而父亲的怎么办?可以知道,点v到其父亲这一叉就是n-sum(v)了,sum(v)指的是以v为根的子树的节

poj 1655 and 3107 and 2378 树形dp(树的重心问题)

简单的树形dp,顺便学习了树的重心的概念,即以该点为根的树的最大子树的结点数最少. poj 1655: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 20001; 7 int head[N]; 8 int balance[N]; 9 int child[N]; 10 int n, e; 11 12 struct

POJ 1655 Balancing Act(求树的重心)

题目大意: 就是要求树的重心,重心的定义就是删除这个点使得森林尽量平衡. 也可以让分治子树的时候使得每颗子树的数量在nlogn以内. 思路分析: son [x] 表示x的子树的数量  不包括自己. balance 表示最大的森林的节点数. 最后我们要让最大的balance 最小. balance = max (balance ,n - 1 - son[x]  , son[j] +1).. #include <cstdio> #include <iostream> #include

树形DP求树的重心 --SGU 134

令一个点的属性值为:去除这个点以及与这个点相连的所有边后得到的连通分量的节点数的最大值. 则树的重心定义为:一个点,这个点的属性值在所有点中是最小的. SGU 134 即要找出所有的重心,并且找出重心的属性值. 考虑用树形DP. dp[u]表示割去u点,得到的连通分支的节点数的最大值. tot[u]记录以u为根的这棵子树的节点数总和(包括根). 则用一次dfs即可预处理出这两个数组.再枚举每个点,每个点的属性值其实为max(dp[u],n-tot[u]),因为有可能最大的连通分支在u的父亲及以上