美團CodeM 初賽 A倫 最長樹鏈 xjb枚舉+dfs

[編程題] 最長樹鏈

時間限制:1秒

空間限制:32768K

樹鏈是指樹裏的一條路徑。美團外賣的形象代言人袋鼠先生最近在研究一個特殊的最長樹鏈問題。現在樹中的每個點都有一個正整數值,他想在樹中找出最長的樹鏈,使得這條樹鏈上所有對應點的值的最大公約數大於1。請求出這條樹鏈的長度。 
輸入描述:
第1行:整數n(1 ≤ n ≤ 100000),表示點的個數。
第2~n行:每行兩個整數x,y表示xy之間有邊,數據保證給出的是一棵樹。
第n+1行:n個整數,依次表示點1~n對應的權值(1 ≤ 權值 ≤ 1,000,000,000)。


輸出描述:
滿足最長路徑的長度

輸入例子:
4
1 2
1 3
2 4
6 4 5 2

輸出例子:
3

1具體就是枚舉所以質因子,然後dfs的時候只走有當前這個質因子的點。。。這樣的話正面看來複雜度貌似很大,最多有10W個質因子,每次dfs複雜度上限也是10W,,貌似會超時? 這個時候要從另外一個角度計算複雜度啦。我們對一個數來考慮,他會被幾次dfs遍歷到?。很顯然就是它的質因子的數量次,,一個數的質因子數比logn還要小很多。所以所有數只會被遍歷到最多 nlogn次,複雜度也差不多nlogn級別的,就不會超時了

#include<iostream>
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<queue>
#include<string.h>
#include<cstring>
#include<vector>
#include<time.h>
#include<stdlib.h>
using namespace std;
#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f
#define FIN freopen("input.txt","r",stdin)
#define mem(x,y) memset(x,y,sizeof(x))
typedef unsigned long long ULL;
typedef long long LL;
#define fuck(x) cout<<"q"<<endl;
#define MX 111111
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef pair<pair<int,int>,int> PIII;
typedef pair<int,int> PII;
const double eps=1e-8;
int n;
int val[MX];
bool isprime[MX];
int prime[MX],prime_cnt;
void prime_init()
{
    prime_cnt=0;
    mem(isprime,1);
    for(int i=2; i<MX; i++)
    {
        if(isprime[i])prime[prime_cnt++]=i;
        for(int j=0; j<prime_cnt&&prime[j]*i<MX; j++)
        {
            isprime[prime[j]*i]=0;
            if(i%prime[j]==0)break;
        }
    }
}
int head[MX],edge_cnt;
struct Edge
{
    int nxt,to;
} E[MX*2];
void edge_init()
{
    mem(head,-1);
    edge_cnt=0;
}
void edge_add(int u,int v)
{
    E[edge_cnt].nxt=head[u];
    E[edge_cnt].to=v;
    head[u]=edge_cnt++;
}
int vis[MX];
int num[MX];
map<int,vector<int> >mp;
int w;
int dfs(int u,int fa)
{

    num[u]=1;
    int MM=0,M=0;
    int ans=0;
    for(int i=head[u]; ~i; i=E[i].nxt)
    {
        int v=E[i].to;
        if(v==fa||val[v]%w)continue;
        ans=max(ans,dfs(v,u));
        if(num[v]>MM)M=MM,MM=num[v];
        else if(num[v]>M)M=num[v];
    }
    num[u]=M+MM+1;
    return max(ans,num[u]);
}
int solve(int u)
{
    w=u;
    int ans=0;
    for(auto i:mp[u])
    {
        if(vis[i]==0)ans=max(ans,dfs(i,-1));
    }
    for(auto i:mp[u])vis[i]=0;
    return ans;
}
int main()
{
    prime_init();
    FIN;
    while(cin>>n)
    {
        edge_init();
        mp.clear();
        for(int i=1; i<n; i++)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            edge_add(u,v);
            edge_add(v,u);
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&val[i]);
            int x=val[i];
            for(int j=0; prime[j]<=sqrt(x+0.5); j++)
            {
                if(x%prime[j]==0)mp[prime[j]].push_back(i);
                while(x%prime[j]==0)x/=prime[j];
            }
            if(x!=1)mp[x].push_back(i);
        }
        int ans=0;
        for(auto i:mp)
        {
            ans=max(ans,solve(i.first));
        }
        cout<<ans<<endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章