Outline of Solution: The total number of a selected node as the root node, provided DP [i] i is expressed in the root of the tree, dp [i] = j satisfy its child nodes D [j] and the sum plus 1 (root). Just look for the largest sub-tree node dfs process, the number of nodes and above it compare, you can find the center of gravity of the tree.
Title effect: For unrooted tree, to find such a point that point to the root tree rooted tree, the smallest sub-tree maximum (the maximum node after the node selecting its subtree) of the nodes.
https://blog.csdn.net/qq_41289920/article/details/83933631
https://blog.csdn.net/llzhh/article/details/78146548
https://blog.csdn.net/imzxww/article/details/81776219
template:
#include<iostream> #include<cstdio> #include<vector> #include<queue> #include<utility> #include<stack> #include<algorithm> #include<cstring> #include<string> #include<cmath> #include<set> #include<map> using namespace std; const int maxn = 5e4 + 5; int head[maxn], to[maxn << 1], nx[maxn << 1], tot; bool vst[maxn]; int Min = 0x3f3f3f3f, key; int cnt[maxn], n; vector <int> vec; void add_edge(int u, int v) { to[tot] = v, nx[tot] = head[u], head[u] = tot++; swap(u, v); to[tot] = v, nx[tot] = head[u], head[u] = tot++; } int dfs(int u, int par) { cnt[u] = 1; int Max = 0; for(int i = head[u]; ~i; i = nx[i]) { int v = to[i]; if(v != par) { cnt[u] += dfs(v, u); Max = max(Max, cnt[v]); } } if(Max < n - cnt[u]) Max = n - cnt[u]; if(Max < Min) { vec.clear(); Min = Max; vec.push_back(u); } else if(Max == Min) { vec.push_back(u); } return cnt[u]; } int main() { memset(head, -1, sizeof(head)); tot = 0; Min = 0x3f3f3f3f; scanf("%d", &n); for(int i = 1, u, v; i < n; i++) { scanf("%d%d", &u, &v); add_edge(u, v); } dfs(1, 1); sort(vec.begin(), vec.end()); for(int i = 0; i < vec.size(); i++) printf("%d%c", vec[i], i + 1 == vec.size() ? '\n' : ' '); return 0; }
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define inf 1<<30 int n,dp[101],node,minans; vector<int> edge[101]; int dfs(int m,int fa) { int maxnode=0; for(int i=0;i<edge[m].size();i++) { int tmp=Edge [m] [I]; IF (tmp =! FA) { DP [m] + = DFS (tmp, m); maxnode = max (maxnode, DP [tmp]); // get the maximum sub-tree nodes } } maxnode = max (maxnode, n--DP [m]); // then the upper nodes compared IF (maxnode < minans) { minans = maxnode; Node = m; } return DP [m]; } int main () { the while (CIN >> n-) { for (int i=1;i<=n;i++) edge[i].clear(); int a,b; for(int i=1;i<=n-1;i++) { cin>>a>>b; edge[a].push_back(b); edge[b].push_back(a); } for(int i=1;i<=n;i++) //初始化都是1,即根节点本身 { dp[i]=1; } minans=inf; dfs(1,-1); cout<<minans<<" "<<node<<endl; } return 0; }
Weighted center of gravity of the tree: ---- explain edition: https://blog.csdn.net/qq_35781950/article/details/76854246
#include<bits/stdc++.h>//树的重心版本 using namespace std; const int maxn=4e5+20; struct Node{ int to; int next; }node[maxn]; int len; int head[maxn]; void add(int a,int b){ node[len].to=b; node[len].next=head[a]; head[a]=len++; } int m; bool vis[maxn]; int c_tre[maxn]; int num[maxn]; bool visit[maxn];//对应权重点 int k; long long all=0; int bkbk; void Init(){ len=0; memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); memset(c_tre,0,sizeof(c_tre)); memset(visit,false,sizeof(visit)); memset(num,0,sizeof(num)); all=0; bkbk=0; } void dfs1(int x,int pre){ if(visit[x]) {num[x]=1;} for(int i=head[x];i!=-1;i=node[i].next){ int to=node[i].to; if(to==pre)continue; dfs1(to,x); num[x]+=num[to]; } return ;//返回的这个num 带自身。 } void dfs(int u,int fa)//求树的带权重心模板。 { int mx=k*2-num[u]; for(int i=head[u]; i!=-1; i=node[i].next) { int v=node[i].to; if(v==fa) continue; mx=max(mx,num[v]); } if(mx<=k){ bkbk=u; return ; } for(int i=head[u]; i!=-. 1 ; I = Node [I] .next) { int V = Node [I] .to; IF (FA == V) Continue ; DFS (V, U); IF (bkbk) return ; } } void dfs3 ( int C, int len) { // this search process is cumulative seek distance from the center of gravity of each point VIS [C] = to true ; IF (Visit [C]) = All + len; for ( int I = head [C]; ! = I - . 1 ; I = Node [I] .next) { int to = Node [I] .to; IF(vis[to]) continue; dfs3(to,len+1); } } int main() { int t; int a,b; scanf("%d%d",&m,&k); Init(); for(int i=0;i<2*k;i++){ scanf("%d",&a); visit[a]=true; } //k*=2; for(int I = 0 ; I <M- . 1 ; I ++ ) { Scanf ( " % D% D " , & A, & B); the Add (B, A); the Add (A, B); } DFS1 ( . 1 , - . 1 ); // record what weights. DFS ( . 1 , - . 1 ); // calculate the weighted center of gravity. = All 0 ; Memset (VIS, to false , the sizeof (VIS)); dfs3 (bkbk, 0 ); // calculate the weight of each point from the center of gravity and weight. cout<<all<<endl; return 0; }
https://blog.csdn.net/q1093383371/article/details/52985375
#include <cstdio> #include <Vector> #include <the iostream> #include <Queue> #include <CString> #define MAXN 200005 the using namespace STD; // find the center of gravity of the tree int n-, popu [MAXN], TOT = 0 ; Vector < int > G [MAXN]; void the init () { Scanf ( " % D " , & n-); // represents the number of towns int X, Y; for ( int I = . 1 ; I <n-; I ++) // n-1 edges form a tree represents { scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } for(int i=1;i<=n;i++) { scanf("%d",&popu[i]);//权值 tot+=popu[i];//权值总和 } } bool vis[maxn]; int fa[maxn],sum[maxn],dist[maxn],maxsum[maxn]; long long cost[maxn]; void DFS(int i) { vis[i]=true; sum[i]=popu[i]; cost[i]=0; for(int k=0;k<g[i].size();k++) { int j=g[i][k]; if(vis[j]) continue; DFS(j); sum[i]+=sum[j]; maxsum[i]=max(maxsum[i],sum[j]); cost[i]+=cost[j]+sum[j]; } maxsum[i]=max(maxsum[i],tot-sum[i]); } void solve() { init(); DFS(1); int sum_min=tot,x; for(int i=1;i<=n;i++) { if(maxsum[i]<sum_min) { sum_min=maxsum[i]; x=i; } } for(int i=1;i<=n;i++) { if(maxsum[i]==sum_min) { printf("%d ",i); } } printf("\n"); memset(vis,0,sizeof(vis)); DFS(x); cout<<cost[x]<<endl; } int main() { //freopen("in.txt","r",stdin); solve(); return 0; }