题目大意
给定一颗边权树,对于任意i求出f[i]表示一条长度为i的简单路径gcd的最大值。
瞎做
我们可以把每条边挂在其的约数上,使用质因数分解。
对每个gcd做一下,对保留的所有边构出新树,然后对于所有这些边涉及到的点形成的每个联通块用两遍dfs求直径,最终得到森林的最长链。
设最长链为k,当前枚举的gcd为v,则
f[k]=max(f[k],v)
这样做显然会错,但我们注意到
f[i]>=f[i+1]
倒着取max一下就是对的了
注意卡常
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int maxn=400000+10,maxd=1000000,maxtot=15000000;
int h[maxn],go[maxn*2],next[maxn*2],a[maxn][2];
int h2[maxd+10],g2[maxtot+10],n2[maxtot+10];
int h3[maxn],g3[maxn*2],n3[maxn*2];
int fa[maxn],rank[maxn],data[maxn][3];
int dfn[maxn*2],fi[maxn],d[maxn],rmq[maxn*2][25],zjy[maxn*2],two[25];
int pri[maxd+10],b[20],c[20],flag[maxn],dx[maxn];
bool pd[maxd+10],czy[maxn];
int sta[maxn],f[maxd+10];
bool bz[maxn];
int i,j,k,l,r,t,n,m,cnt,top,tot,num,sum,mx,ans,ans2,ans3,wdc,gjx;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while (ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
void prepare(){
int i;
fo(i,2,maxd){
if (!pd[i]) pri[++num]=i;
fo(j,1,num){
if ((ll)i*pri[j]>maxd) break;
pd[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
}
void add(int x,int y){
go[++tot]=y;
next[tot]=h[x];
h[x]=tot;
}
void add2(int x,int y){
g2[++cnt]=y;
n2[cnt]=h2[x];
h2[x]=cnt;
}
void gao(int x,int y,int id){
if (x==sum+1){
add2(y,id);
return;
}
int i,j=1;
fo(i,0,c[x]){
gao(x+1,y*j,id);
j*=b[x];
}
}
void link(int id,int v){
int i;
sum=0;
fo(i,1,num){
if (pri[i]*pri[i]>v) break;
if (v%pri[i]==0){
b[++sum]=pri[i];
c[sum]=0;
while (v%pri[i]==0){
v/=pri[i];
c[sum]++;
}
}
}
if (v>1){
b[++sum]=v;
c[sum]=1;
}
gao(1,1,id);
}
void dfs(int x,int y){
//d[x]=d[y]+1;
//dfn[++top]=x;
//fi[x]=top;
int t=h[x];
while (t){
if (go[t]!=y){
dfs(go[t],x);
//dfn[++top]=x;
}
t=next[t];
}
}
void dfs1(int x,int y){
bz[x]=1;
d[x]=d[y]+1;
if (!ans2||d[x]>d[ans2]) ans2=x;
int t=h3[x];
while (t){
if (g3[t]!=y) dfs1(g3[t],x);
t=n3[t];
}
}
void dfs2(int x,int y){
d[x]=d[y]+1;
if (!ans3||d[x]>d[ans3]) ans3=x;
int t=h3[x];
while (t){
if (g3[t]!=y) dfs2(g3[t],x);
t=n3[t];
}
}
void add3(int x,int y){
g3[++gjx]=y;
n3[gjx]=h3[x];
h3[x]=gjx;
}
void work(int v){
int i,j,k,l,r,t;
ans=wdc=gjx=0;
r=h2[v];
while (r){
t=g2[r];
j=a[t][0];k=a[t][1];
if (!czy[j]) dx[++wdc]=j,h3[j]=0,czy[j]=1;
if (!czy[k]) dx[++wdc]=k,h3[k]=0,czy[k]=1;
add3(j,k);add3(k,j);
r=n2[r];
}
fo(i,1,wdc) bz[dx[i]]=0;
fo(i,1,wdc)
if (!bz[dx[i]]){
ans2=ans3=0;
dfs1(dx[i],0);
dfs2(ans2,0);
if (d[ans3]>ans) ans=d[ans3];
}
f[ans]=v;
fo(i,1,wdc) czy[dx[i]]=0;
}
void write(int x){
if (!x){
putchar('0');
putchar('\n');
return;
}
top=0;
while (x){
sta[++top]=x%10;
x/=10;
}
while (top){
putchar('0'+sta[top]);
top--;
}
putchar('\n');
}
int main(){
freopen("walk.in","r",stdin);freopen("walk.out","w",stdout);
n=read();
prepare();
fo(i,1,n-1){
j=read();k=read();l=read();
mx=max(mx,l);
add(j,k);add(k,j);
a[i][0]=j;a[i][1]=k;
link(i,l);
}
dfs(1,0);
d[0]=-1;
fo(i,1,mx)
if (h2[i]) work(i);
fd(i,n-1,1) f[i]=max(f[i],f[i+1]);
fo(i,1,n) write(f[i]);
}