【题解】【神奇校内POIN模拟赛】小凯的疑惑
题外话:
sol:套路
我:???这是什么神仙思路?、
给定一棵有\(n\)个节点的树,你可以选择一些点,这些点不能相邻
你所得到的总价值为这些节点的权值的乘积
求最大的价值\(mod 998244353\)
sol
考虑一个神奇的东西:对数
显然我们有:
如果
\[ab=c
\]
那么
\[log_x(a)+log_x(b)=log(c)
\]
所以,问题转化为树的最大权独立集
经典问题,树形DP即可
code
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=200010;
const int M=N;
const int mod=998244353;
inline void read(int &x) {
x=0;
int 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();
}
x*=f;
}
struct note {
int t;
int next;
};
int cnt;
int head[N];
note e[M<<1];
int n;
inline void add(int x,int y) {
e[++cnt].t=y;
e[cnt].next=head[x];
head[x]=cnt;
}
double f[N][2];
double val[N];
int v[N];
void dfs(int p,int fa) {
f[p][0]=0;
f[p][1]=val[p];
for(int i=head[p];i+1;i=e[i].next) {
int t=e[i].t;
if (t==fa) {
continue;
}
dfs(t,p);
f[p][1]+=f[t][0];
f[p][0]+=max(f[t][1],f[t][0]);
}
}
int ans=1;
void dfs2(int p,int fa,bool d) {
if (d) {
ans=(1ll*v[p]*ans)%mod;
}
for(int i=head[p];i+1;i=e[i].next) {
int t=e[i].t;
if (t==fa) {
continue;
}
if (d) {
dfs2(t,p,0);
} else {
if (f[t][1]>f[t][0]) {
dfs2(t,p,1);
} else {
dfs2(t,p,0);
}
}
}
}
int main() {
read(n);
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++) {
read(v[i]);
val[i]=log10(v[i]);
}
for(int i=1;i<n;i++) {
int x,y;
read(x),read(y);
add(x,y);
add(y,x);
}
dfs(1,-1);
if (f[1][0]<f[1][1]) {
dfs2(1,-1,1);
} else {
dfs2(1,-1,0);
}
printf("%d\n",ans);
return 0;
}