team2012-F3-sol-0006
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
题意:给定一个树,节点带有权值,现在可以去掉其中一个节点并将树分成多个部分,每部分的权值为其中节点的权值和,问各部分权值乘积的最大值。
解法:先dfs一遍化为有根树,并记录每个子树的权值和sum[i],再枚举删除哪个节点x。
如果x不是是根,乘积由(sum[root]-sum[x])*sum[son1]*sum[son2]*...得到,是根将第一项去掉即可,要用高精度。
}}}
{{{
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 100004;
int w[MAXN], fa[MAXN], sum[MAXN];
vector<int> conn[MAXN];
struct bign
{
int dt[1000], len;
bign(int x = 0)
{
len = 1;
dt[len] = x;
while(dt[len] >= 10)
{
dt[len+1] = dt[len]/10;
dt[len++] %= 10;
}
}
void operator*=(int x)
{
LL cf = 0, tmp;
for(int i=1;i<=len;i++)
{
tmp = dt[i];
tmp = tmp*x + cf;
dt[i] = tmp%10;
cf = tmp/10;
}
while(cf)
{
dt[++len] = cf%10;
cf /= 10;
}
}
bool operator<(bign& x)
{
if(len < x.len) return 1;
if(len > x.len) return 0;
for(int i=len;i>=1;i--)
{
if(dt[i] < x.dt[i]) return 1;
if(dt[i] > x.dt[i]) return 0;
}
return 0;
}
void out()
{
for(int i=len;i>=1;i--)
cout<<dt[i];
cout<<endl;
}
};
void dfs(int x)
{
sum[x] = w[x];
for(int i=0;i<conn[x].size();i++)
{
int v = conn[x][i];
if(v != fa[x])
{
fa[v] = x;
dfs(v);
sum[x] += sum[v];
}
}
}
int main()
{
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>w[i];
conn[i].clear();
}
for(int i=1;i<n;i++)
{
int a, b;
cin>>a>>b;
conn[a].push_back(b);
conn[b].push_back(a);
}
memset(fa, 0, sizeof(fa));
dfs(1);
bign ans;
for(int i=1;i<=n;i++)
{
bign tmp(1);
for(int j=0;j<conn[i].size();j++)
{
int v = conn[i][j];
if(v == fa[i])
tmp *= sum[1]-sum[i];
else
tmp *= sum[v];
}
if(ans < tmp)
ans = tmp;
}
ans.out();
}
return 0;
}
}}}
题意:给定一个树,节点带有权值,现在可以去掉其中一个节点并将树分成多个部分,每部分的权值为其中节点的权值和,问各部分权值乘积的最大值。
解法:先dfs一遍化为有根树,并记录每个子树的权值和sum[i],再枚举删除哪个节点x。
如果x不是是根,乘积由(sum[root]-sum[x])*sum[son1]*sum[son2]*...得到,是根将第一项去掉即可,要用高精度。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int MAXN = 100004;
int w[MAXN], fa[MAXN], sum[MAXN];
vector<int> conn[MAXN];
struct bign
{
int dt[1000], len;
bign(int x = 0)
{
len = 1;
dt[len] = x;
while(dt[len] >= 10)
{
dt[len+1] = dt[len]/10;
dt[len++] %= 10;
}
}
void operator*=(int x)
{
LL cf = 0, tmp;
for(int i=1;i<=len;i++)
{
tmp = dt[i];
tmp = tmp*x + cf;
dt[i] = tmp%10;
cf = tmp/10;
}
while(cf)
{
dt[++len] = cf%10;
cf /= 10;
}
}
bool operator<(bign& x)
{
if(len < x.len) return 1;
if(len > x.len) return 0;
for(int i=len;i>=1;i--)
{
if(dt[i] < x.dt[i]) return 1;
if(dt[i] > x.dt[i]) return 0;
}
return 0;
}
void out()
{
for(int i=len;i>=1;i--)
cout<<dt[i];
cout<<endl;
}
};
void dfs(int x)
{
sum[x] = w[x];
for(int i=0;i<conn[x].size();i++)
{
int v = conn[x][i];
if(v != fa[x])
{
fa[v] = x;
dfs(v);
sum[x] += sum[v];
}
}
}
int main()
{
int n;
while(cin>>n)
{
for(int i=1;i<=n;i++)
{
cin>>w[i];
conn[i].clear();
}
for(int i=1;i<n;i++)
{
int a, b;
cin>>a>>b;
conn[a].push_back(b);
conn[b].push_back(a);
}
memset(fa, 0, sizeof(fa));
dfs(1);
bign ans;
for(int i=1;i<=n;i++)
{
bign tmp(1);
for(int j=0;j<conn[i].size();j++)
{
int v = conn[i][j];
if(v == fa[i])
tmp *= sum[1]-sum[i];
else
tmp *= sum[v];
}
if(ans < tmp)
ans = tmp;
}
ans.out();
}
return 0;
}