Description

有一颗树,每个点有一个点权,边权都是 \(1\),问路径上的所有点的 gcd 不是 \(1\) 的最长路径是多少?

Solution

分治到每个点时,考虑当前分治范围内经过该点的路径。

对于每个子树,记录一个映射,表示每个数能到达的最深的深度,边搜索边更新即可。

维护当前分治主树的映射,枚举完一个子树后,用子树映射和主树映射中的值更新答案,并将子树映射并入主树映射中。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define foradj(p) for(pair<int,int> pr:g[p])
#define unpii(q,w) int q=pr.first, w=pr.second;
const int N = 200005;

vector <pair<int,int> > g[N];
int dis[N],siz[N],n,m,t1,t2,t3,k[N],vis[N],sum,rt,rtval,val[N],ans;
vector<int> st,wl;
set<int> s;
map<int,int> mp_main,mp_sub;

void findroot(int p,int ff)
{
    siz[p]=1;
    int mx=0;
    foradj(p)
    {
        unpii(q,w);
        if(!vis[q] && q!=ff)
        {
            findroot(q,p);
            siz[p]+=siz[q];
            mx=max(mx,siz[q]);
        }
    }
    mx=max(mx,sum-siz[p]);
    if(mx<rtval) rtval=mx, rt=p;
}

void dfs(int p,int ff,int x)
{
    if(x==1) return;
    mp_sub[x]=max(mp_sub[x],dis[p]);
    foradj(p)
    {
        unpii(q,w);
        if(!vis[q] && q!=ff)
        {
            dis[q]=dis[p]+1;
            dfs(q,p,__gcd(x,val[q]));
        }
    }
}

void solve(int p)
{
    vis[p]=1;
    mp_main.clear();
    mp_main[val[p]]=0;
    foradj(p)
    {
        unpii(q,w);
        if(!vis[q])
        {
            dis[q]=1;
            dfs(q,p,__gcd(val[p],val[q]));
            /*cout<<"q="<<q<<" p="<<p<<endl;
            cout<<"sub: ";
            for(auto i:mp_sub) cout<<i.first<<" ";
            cout<<endl;
            cout<<"main:";
            for(auto i:mp_main) cout<<i.first<<" ";
            cout<<endl;*/
            for(auto i:mp_main)
            {
                for(auto j:mp_sub)
                {
                    if(__gcd(i.first,j.first)>1)
                    {
                        //cout<<i.first<<" "<<j.first<<endl;
                        ans=max(ans,i.second+j.second+1);
                    }
                }
            }
            for(auto i:mp_sub)
            {
                mp_main[i.first]=max(mp_main[i.first],i.second);
            }
            mp_sub.clear();
        }
    }
    foradj(p)
    {
        unpii(q,w);
        if(!vis[q])
        {
            sum=siz[q];
            rtval=1e18;
            findroot(q,0);
            solve(rt);
        }
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>val[i];
    }
    for(int i=1;i<n;i++)
    {
        cin>>t1>>t2;
        g[t1].push_back({t2,1});
        g[t2].push_back({t1,1});
    }
    sum=n;
    rtval=1e18;
    findroot(1,0);
    solve(rt);
    for(int i=1;i<=n;i++) if(val[i]>1) ans=max(ans,1ll);
    cout<<ans<<endl;
}

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-12-23
  • 2020-03-30
  • 2021-05-15
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-08-10
  • 2022-12-23
  • 2021-08-11
  • 2022-03-08
  • 2021-11-16
相关资源
相似解决方案