重心就是把这个点删掉后剩下的子树大小最小,siz数组表示以x为根的子树总的大小,maxsiz数组表示以x为根的每个子树的最大的大小,sum表示整个树的大小,那么sum-siz就是除了x为根所有子树外的那颗子树的大小。
代码:
cpp
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define fi first
#define se second
const ll mod=1e9+7;
const int N=2e5+10;
#define int ll
const double eps=1e-6;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
int n,sum;
vector<int> v[N];
int siz[N],root,maxsiz[N];
void dfs(int x,int f){
siz[x]=1;
for(auto y:v[x]){
if(y==f) continue;
dfs(y,x);
siz[x]+=siz[y];
maxsiz[x]=max(maxsiz[x],siz[y]);
}
maxsiz[x]=max(maxsiz[x],sum-siz[x]);
if(maxsiz[x]<maxsiz[root])
root=x;
}
void solve(){
cin>>n;
for(int i=1;i<n;i++){
int x,y;cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
sum=maxsiz[root=0]=n;
dfs(1,0);
cout<<root<<' '<<maxsiz[root];
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t=1;
//cin>>t;
while (t--){
solve();
}
return 0;
}
两次dfs里的dis最大值就是直径的两端
代码:
cpp
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
#define fi first
#define se second
const ll mod=1e9+7;
const int N=2e5+10;
#define int ll
const double eps=1e-6;
ll qpow(ll a,ll b){
ll res=1;
while(b){
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
int n,a[N];
int dis[N],root1,root2;
vector<int>v[N];
void dfs1(int x,int f){
dis[x]=dis[f]+a[x];
if(dis[x]>dis[root1]){
root1=x;
}
for(auto y:v[x]){
if(y==f) continue;
dfs1(y,x);
}
}
void dfs2(int x,int f){
dis[x]=dis[f]+a[x];
if(dis[x]>dis[root2]){
root2=x;
}
for(auto y:v[x]){
if(y==f) continue;
dfs2(y,x);
}
}
void solve(){
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>a[i];
}
for(int i=1;i<n;i++){
int x,y;cin>>x>>y;
v[x].push_back(y);
v[y].push_back(x);
}
dis[root1=n+1]=dis[root2=n+2]=-0x3f3f3f3f;
dfs1(1,0);
dfs2(root1,0);
cout<<dis[root2];
}
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int t=1;
//cin>>t;
while (t--){
solve();
}
return 0;
}