树的重心
int sz[N],mins = 1e9,rt;
void dfs(int u,int fa) {
sz[u] = 1; int maxs = 0;
for(int i = head[u]; i;i = e[i].nxt) {
int v = e[i].v; if(v == fa) continue;
dfs(v,u);
sz[u] += sz[v];
if(maxs < sz[v]) maxs = sz[v];
}
maxs = max(maxs,n-sz[u]);
if(maxs < mins) mins = maxs,rt = u;
}
树的直径
-
写法1
我以前的写法
ll d[N],ans;
void dfs(int u,int fa) {
ll maxd1 = 0,maxd2 = 0;
for(int i = head[u]; i;i = e[i].nxt) {
int v = e[i].v; if(v == fa) continue;
dfs(v,u);
ll tmp = d[u]+e[i].w;
d[u] = max(d[u],tmp);
if(tmp >= maxd1) maxd2 = maxd1,maxd1 = tmp;
else if(tmp > maxd2) maxd2 = tmp;
}
ans = max(ans,maxd1+maxd2);
}
-
写法2
新看到的写法
ll d[N],ans;
void dfs(int u,int fa) {
for(int i = head[u]; i;i = e[i].nxt) {
int v = e[i].v; if(v == fa) continue;
dfs(v,u);
ans = max(ans,d[u]+d[v]+e[i].w);
d[u] = max(d[u],d[v]+e[i].w);
}
}
倍增求lca
void dfs(int u,int _fa) {
dep[u] = dep[_fa]+1; fa[u][0] = _fa;
for(int i = 1;i <= 19; ++i) fa[u][i] = fa[fa[u][i-1]][i-1];
for(int i = head[u]; i;i = e[i].nxt) {if(e[i].v != _fa) dfs(e[i].v,u);}
}
int lca(int x,int y) {
if(dep[x] < dep[y]) swap(x,y);
for(int i = 19;i >= 0; --i) if(dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if(x == y) return x;
for(int i = 19;i >= 0; --i) if(fa[x][i] != fa[y][i]) x = fa[x][i],y = fa[y][i];
return fa[x][0];
}