【填坑】loj6159. 「美团 CodeM 初赛 Round A」最长树链
水一水
枚举各个质数,把是这个数倍数的点留下,跑直径,没了
1 #include <bits/stdc++.h> 2 using namespace std; 3 int h,t,n,p,q,M,N; 4 int dis[200001],lis[200001],fir[200001],nex[400001],to[400001]; 5 vector<int> po[200001]; 6 map<int,int> ma; 7 bitset<200001> vis,ok,v; 8 void add(int p,int q) 9 { 10 to[++M]=q;nex[M]=fir[p];fir[p]=M; 11 } 12 int bfs(int now) 13 { 14 dis[now]=1;vis[now]=1;int lo=0,id=0; 15 v.reset();v[now]=1; 16 for(lis[h=t=1]=now;h<=t;h++) 17 for(int i=fir[lis[h]];i;i=nex[i]) 18 if(ok[to[i]] && !v[to[i]]) 19 { 20 lis[++t]=to[i]; 21 vis[to[i]]=1;v[to[i]]=1; 22 dis[to[i]]=dis[lis[h]]+1; 23 if(dis[to[i]]>lo) lo=dis[to[i]],id=to[i]; 24 } 25 return id; 26 } 27 int main() 28 { 29 scanf("%d",&n); 30 for(int i=1;i<n;i++) 31 scanf("%d%d",&p,&q),add(p,q),add(q,p); 32 for(int i=1;i<=n;i++) 33 { 34 scanf("%d",&t); 35 for(int j=2;j<=sqrt(t);j++) 36 { 37 if(t%j==0) 38 po[ma[j]?ma[j]:(ma[j]=++N)].push_back(i); 39 while(t%j==0) 40 t/=j; 41 } 42 if(t>1) po[ma[t]?ma[t]:(ma[t]=++N)].push_back(i); 43 } 44 int L=0; 45 for(int i=1;i<=N;i++) 46 { 47 ok.reset();vis.reset(); 48 for(int j=0;j<po[i].size();j++) 49 ok[po[i][j]]=1;//,printf("%d ",po[i][j]); 50 // puts(""); 51 for(int j=0;j<po[i].size();j++) 52 if(!vis[po[i][j]]) 53 L=max(L,dis[bfs(bfs(po[i][j]))]); 54 } 55 printf("%d\n",L); 56 return 0; 57 }