1. 程式人生 > >[LOJ 6159] 最長樹鏈

[LOJ 6159] 最長樹鏈

read ++ 素數 str emp 長度 names space i++

看到要求gcd不為1所以肯定在這條答案鏈上都是一個質數的倍數,所以就會產生一個很暴力的想法

沒錯,正解就是這樣的暴力

只讓走是i(素數)倍數的點,作最長鏈

最長鏈可以樹形dp或兩遍bfs,一遍找端點,一遍過長度即可

復雜度:未證

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#include<queue>
#include<vector> 
#include<cmath>
using
namespace std; inline int read() { int f=1,ans=0;char c; while(c<0||c>9){if(c==-)f=-1;c=getchar();} while(c>=0&&c<=9){ans=ans*10+c-0;c=getchar();} return f*ans; } map<int,int> ma; struct node{ int u,v,nex; }x[200001]; int cnt,n,head[100001]; void add(int
u,int v) { x[cnt].u=u,x[cnt].v=v,x[cnt].nex=head[u],head[u]=cnt++; } int v[100001],sry,have[100001]; int vis[100001]; int dis[100001]; vector<int> ve[100005]; int vis1[100001]; int maxn; int bfs(int u) { queue<int> que; int ans=u; que.push(u); vis[u]=1,dis[u]=1; while(!que.empty()) {
int xx=que.front();que.pop(); for(int i=head[xx];i!=-1;i=x[i].nex) { if(have[x[i].v]==0) continue; if(vis[x[i].v]) continue; vis[x[i].v]=1; dis[x[i].v]=dis[xx]+1; if(dis[x[i].v]>dis[ans]) ans=x[i].v; que.push(x[i].v); } } while(!que.empty()) que.pop(); que.push(ans),vis1[ans]=1,dis[ans]=1; while(!que.empty()) { int xx=que.front();que.pop(); for(int i=head[xx];i!=-1;i=x[i].nex) { if(have[x[i].v]==0) continue; if(vis1[x[i].v]) continue; dis[x[i].v]=dis[xx]+1; vis1[x[i].v]=1; if(dis[x[i].v]>dis[ans]) ans=x[i].v; que.push(x[i].v); } } return dis[ans]; } int main() { memset(head,-1,sizeof(head)); n=read(); for(int i=1;i<n;i++) { int u=read(),v=read(); add(u,v),add(v,u); } for(int i=1;i<=n;i++) v[i]=read(); for(int i=1;i<=n;i++) { int x=v[i]; for(int j=2;j<=sqrt(x);j++) { if(x%j!=0) continue; if(ma[j]==0) ma[j]=++sry; ve[ma[j]].push_back(i); while(x%j==0) x/=j; } if(x!=1) { if(ma[x]==0) ma[x]=++sry; ve[ma[x]].push_back(i); } } for(int i=1;i<=sry;i++) { int size=ve[i].size(); for(int j=0;j<size;j++) have[ve[i][j]]=1,vis[ve[i][j]]=0,vis1[ve[i][j]]=0; for(int j=0;j<size;j++) { if(vis[ve[i][j]]==1) continue; maxn=max(maxn,bfs(ve[i][j])); } for(int j=0;j<size;j++) have[ve[i][j]]=0,vis[ve[i][j]]=1,vis1[ve[i][j]]=1; } cout<<maxn; }
View Code

[LOJ 6159] 最長樹鏈