赞
踩
传送门:牛客
题目描述:
题目较长,此处省略
输入:
8
bessie 3 2 6 8
folder1 2 3 4
file1 0
folder2 1 5
file2 0
folder3 1 7
file3 0
file4 0
输出:
42
感觉是一道较难的二次扫描换根dp的题目
主要思路:
l e a f _ s i z e 存 储 的 是 当 前 v 节 点 的 所 有 叶 子 节 点 的 个 数 leaf\_size存储的是当前v节点的所有叶子节点的个数 leaf_size存储的是当前v节点的所有叶子节点的个数
对于第一部分来说,我们考虑一下我们的文件路径的移动方式,对于我们的兄弟结点中的每一个叶子结点,我们都是需要我们的当前的节点往上移动一步,然后再往下移动到各个节点.这一部分的总贡献就是: 3 ∗ ( l e a f _ s i z e [ u ] − l e a f _ s i z e [ v ] ) + f [ u ] − f [ v ] − w [ u ] [ v ] ∗ l e a f _ s i z e [ v ] 3*(leaf\_size[u]-leaf\_size[v])+f[u]-f[v]-w[u][v]*leaf\_size[v] 3∗(leaf_size[u]−leaf_size[v])+f[u]−f[v]−w[u][v]∗leaf_size[v],注意这一部分我们还需要减去我们的刚开始由 u u u节点往下走到v节点,因为我们的 f [ v ] f[v] f[v]并没有包括这一部分
对于我们的第二部分来说,我们发现需要求出的父亲的父亲的贡献其实在我们的dfs过程中就可以求出来了,为 g [ u ] g[u] g[u].但是类似的,我们还需要加上我们的当前节点v走到节点u的贡献.也就是 3 ∗ ( l e a f _ s i z e [ 1 ] − l e a f _ s i z e [ u ] ) 3*(leaf\_size[1]-leaf\_size[u]) 3∗(leaf_size[1]−leaf_size[u])
对于最终的答案,就是在所有的 f [ u ] + g [ u ] − l e a f _ s i z e [ 1 ] f[u]+g[u]-leaf\_size[1] f[u]+g[u]−leaf_size[1]中取最小值即可,为什么要减一呢,这是因为我们在之前求路径的时候将每一个叶子节点也多加了一个$$符号,所以我们需要在答案过程中减去每一个叶子节点的多余贡献
下面是具体的代码部分:
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <map> #include <set> #include <queue> #include <string.h> #include <stack> #include <deque> using namespace std; typedef long long ll; #define inf 0x3f3f3f3f #define root 1,n,1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 inline ll read() { ll x=0,w=1;char ch=getchar(); for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1; for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x*w; } #define maxn 1000000 #define ll_maxn 0x3f3f3f3f3f3f3f3f const double eps=1e-8; int n; vector<ll>tree[maxn],w[maxn]; ll g[maxn],f[maxn];//记录儿子叶子节点的总路径/除儿子以外的叶子节点的和 ll node_length[maxn],leaf_size[maxn]; void dfs1(int u) { if(tree[u].size()) { for(int i=0;i<tree[u].size();i++) { int v=tree[u][i]; dfs1(v); leaf_size[u]+=leaf_size[v]; f[u]+=leaf_size[v]*w[u][i]+f[v]; } }else { leaf_size[u]=1; } return ; } ll ans=ll_maxn; void dfs2(int u) { if(tree[u].size()) { for(int i=0;i<tree[u].size();i++) { int v=tree[u][i]; g[v]=3*(leaf_size[1]-leaf_size[u])+g[u]+3*(leaf_size[u]-leaf_size[v])+f[u]-f[v]-leaf_size[v]*w[u][i]; dfs2(v); } ans=min(ans,g[u]+f[u]-leaf_size[1]); } return ; } int main() { n=read();string s;int num;int v; for(int i=1;i<=n;i++) { cin>>s;node_length[i]=s.length(); num=read(); for(int j=1;j<=num;j++) { v=read(); tree[i].push_back(v); } } for(int i=1;i<=n;i++) { for(int j=0;j<tree[i].size();j++) { int v=tree[i][j]; w[i].push_back(node_length[v]+1); } } dfs1(1); dfs2(1); cout<<ans<<endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。