【LCA】BZOJ1776-[Usaco2010 Hol]cowpol 奶牛政坛
【题目大意】
一棵n个点的树,树上每个点属于一个党派,要求每个党派的最远距离点。两点间距离为两点间边的个数。
【思路】
yy一下可知,最远距离点中必有一个是该党派深度最深的一个,那么我们就记下最深的点,然后枚举跑LCA……O(nlongn)裸的倍增LCA。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int MAXN=200000+50; 4 const int DEG=20; 5 int n,k,rt; 6 int dep[MAXN],party[MAXN],maxdep[MAXN],maxpos[MAXN],maxdis[MAXN]; 7 vector<int> E[MAXN]; 8 int anc[MAXN][DEG]; 9 10 void getanc() 11 { 12 for (int i=1;i<DEG;i++) 13 for (int j=1;j<=n;j++) 14 anc[j][i]=anc[anc[j][i-1]][i-1]; 15 } 16 17 int swim(int x,int H) 18 { 19 for (int i=0;H>0;i++) 20 { 21 if (H&1) x=anc[x][i]; 22 H/=2; 23 } 24 return x; 25 } 26 27 int LCA(int u,int v) 28 { 29 if (dep[u]<dep[v]) swap(u,v); 30 u=swim(u,dep[u]-dep[v]); 31 if (u==v) return u;//不知道为什么总是忘掉这句话(╯▔皿▔)╯ ★★★★ 32 for (int i=DEG-1;i>=0;i--) 33 { 34 if (anc[u][i]!=anc[v][i]) 35 { 36 u=anc[u][i]; 37 v=anc[v][i]; 38 } 39 } 40 return (anc[u][0]); 41 } 42 43 void dfs(int x,int d) 44 { 45 dep[x]=d; 46 for (int i=0;i<E[x].size();i++) 47 { 48 int to=E[x][i]; 49 dfs(to,d+1); 50 } 51 } 52 53 void init() 54 { 55 scanf("%d%d",&n,&k); 56 for (int i=1;i<=n;i++) 57 { 58 int p; 59 scanf("%d%d",&party[i],&p); 60 if (p!=0) E[p].push_back(i); 61 else rt=i; 62 anc[i][0]=p; 63 } 64 dfs(rt,0); 65 for (int i=1;i<=n;i++) 66 if (maxdep[party[i]]<dep[i]) 67 { 68 maxdep[party[i]]=dep[i]; 69 maxpos[party[i]]=i; 70 } 71 } 72 73 void solve() 74 { 75 getanc(); 76 memset(maxdis,0,sizeof(maxdis)); 77 for (int i=1;i<=n;i++) 78 { 79 int np=party[i],mp=maxpos[np]; 80 int lca=LCA(i,mp); 81 int nowdis=-2*dep[lca]+dep[i]+dep[mp]; 82 maxdis[np]=max(maxdis[np],nowdis); 83 } 84 for (int i=1;i<=k;i++) printf("%d\n",maxdis[i]); 85 } 86 87 int main() 88 { 89 init(); 90 solve(); 91 return 0; 92 }