链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
题目描述
给出一棵 nnn 个点 n−1n-1n−1 条边的树。树的节点为 1∼n1 \sim n1∼n,节点 iii 具有权值 val[i]val[i]val[i]。每次操作选择一个节点 iii,再选择 val[i]val[i]val[i] 的一个质因子 xxx,然后令 val[i]=val[i]÷xval[i] = val[i] \div xval[i]=val[i]÷x。问:最少操作几次,才能让这棵树变成一棵孤独的树。
孤独的树的定义:不存在一条边连接的两个节点 u vu\ vu v,gcd(val[u],val[v])>1gcd(val[u],val[v])>1gcd(val[u],val[v])>1。
#include<iostream>
#include<cstring>
#include<iostream>
using namespace std;
const int N=1e5+5,M=2e5+5;
int a[N],b[N];
int dp[N][2];
int mp[N],mnp[N];
int h[N],e[M],ne[M],idx;
int val[N];
int n;
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
int cnt=0;
void dfs(int root,int pre,int p)
{
int cnt=0;
while(val[root]%p==0)
{
val[root]/=p;
cnt++;
}
int sum1=0,sum2=0;
if(cnt==0) {
dp[root][1]=dp[root][0]=0;
return ;
}
for(int i=h[root];~i;i=ne[i])
{
int to=e[i];
if(to==pre) continue;
dfs(to,root,p);
sum1+=dp[to][1];
sum2+=min(dp[to][0],dp[to][1]);
}
dp[root][1]=sum2+cnt;
dp[root][0]=sum1;
}
int main()
{
scanf("%d",&n);
for(int i=2;i<1e5+5;i++)
{
if(!mp[i])
{
for(int j=i;j<1e5+5;j+=i)
{
mp[j]=1;
mnp[j]=i;
}
}
}
memset(h,-1,sizeof h);
for(int i=1;i<=n;i++) scanf("%d",&val[i]);
for(int i=1;i<n;i++)
{
int from,to;
scanf("%d%d",&from,&to);
add(from,to);
add(to,from);
}
int res=0;
bool flag=1;
for(int i=1;i<=n;i++)
{
while(val[i]!=1)
{
int p=mnp[val[i]];
dfs(i,0,p);
res+=min(dp[i][0],dp[i][1]);
}
}
printf("%d\n",res);
}