【算法学习】学换根dp有感
自从钻研这换根DP,犹如梁山好汉破了难关。初时只觉这树状结构,分枝繁复,变化多端,哪知竟有此等妙计。每换一根,便能高效算出新解,岂不似宋江指挥众兄弟,调度得当,事半功倍。更妙的是,这容斥之法,恰如兵法计策,分而治之,避开冗余。学之愈深,愈觉精妙,心中豪气顿生,恨不得与众学者痛饮一场,论此技之神通。
感觉这换根dp真的很有意思,也好理解学习(巧的是学之前还做了类似的题目换根)
详细见例题洛谷 P3478 [POI2008] STA-Station
换根dp 其实就是容斥和树形dp的结合。
感觉非常之妙。
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+10;
int n;
ll siz[N];
ll val[N];
ll ans[N];
vector<int> v[N];
void dfs(int u,int fa){
siz[u]=1;
val[u]=val[fa]+1;
for(int i=0;i<v[u].size();i++){
int y=v[u][i];
if(y==fa){
continue;
}
dfs(y,u);
siz[u]+=siz[y];
}
}
void dfs2(int u,int fa){
for(int i=0;i<v[u].size();i++){
int y=v[u][i];
if(y==fa){
continue;
}
ans[y]=ans[u]+siz[1]-2*siz[y];
dfs2(y,u);
}
}
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<n;i++){
int u,vv;
cin>>u>>vv;
v[u].push_back(vv);
v[vv].push_back(u);
}
dfs(1,0);
for(int i=1;i<=n;i++){
ans[1]+=val[i];
}
dfs2(1,0);
ll mx=-1,id=1;
for(int i=1;i<=n;i++){
if(ans[i]>mx){
mx=ans[i];
id=i;
}
}
cout<<id;
return 0;
}