NC253374. qsgg and Money
描述
给定一棵含有 个节点的树。
每个节点都有一个加油站,该节点加油站每升油耗费 元,经过一条边耗费 升油。
定义函数 ,初始车剩余油量为 升,从 点出发到达 点的简单路径所花费的最少的钱。若 ,。
现在你想知道 。
注意:若当前车剩余油量小于该边耗费油量,则无法通过该边。且车剩余油量无上限。
输入描述
输入共 行。
第一行一个整数表示 , 表示节点个数。
第二行 个整数, 表示在 号节点加油站每升油耗费 元 。
接下来 行,每行三个整数 ,表示第 条边连接 ,经过该边耗费 升油 。
输出描述
输出一个整数,表示 。
示例1
输入:
5 1 1 4 5 1 1 2 4 1 3 1 1 5 9 3 4 1
输出:
161
说明:
例如,从 号节点到 号节点的最少用钱方式是:先在 号节点加 升油到达 号节点,再在 号节点加 升油到达 号节点,最后在 号节点加 升油到达 号节点,。C++(clang++ 11.0.1) 解法, 执行用时: 331ms, 内存消耗: 105540K, 提交时间: 2023-06-28 18:59:22
#include<bits/stdc++.h> using namespace std; const int N=200010; int gi() { char ch=getchar(); int f=1,x=0; while(ch<'0' || ch>'9'){if(ch=='-')f=-f; ch=getchar();} while(ch>='0' && ch<='9')x=x*10+ch-48,ch=getchar(); return f*x; } int f[N][51],g[N][51]; int sz[N],c[N]; int n,head[N],cnt; long long ans; struct edge { int to,next,h; }e[N<<1]; void adde(int a,int b,int c) { e[++cnt].to=b; e[cnt].next=head[a]; head[a]=cnt; e[cnt].h=c; } void dfs(int x,int fa) { sz[x]=1; f[x][c[x]]=1; for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(v==fa)continue; dfs(v,x); sz[x]+=sz[v]; for(int j=1;j<=50;j++)f[x][min(c[x],j)]+=f[v][j]; } } void dp(int x,int fa) { for(int i=head[x];i;i=e[i].next) { int v=e[i].to; if(v==fa)continue; for(int j=1;j<=50;j++)g[v][min(c[x],j)]+=f[x][j]+g[x][j]-f[v][j]; //for(int j=1;j<=50;j++)g[v][min(c[x],j)]-=f[v][j]; dp(v,x); for(long long j=1;j<=50;j++) ans+=e[i].h*j*(1ll*sz[v]*g[v][j]+1ll*(n-sz[v])*f[v][j]); } } int main() { n=gi(); for(int i=1;i<=n;i++)c[i]=gi(); int x,y,z; for(int i=1;i<n;i++) { x=gi(); y=gi(); z=gi(); adde(x,y,z); adde(y,x,z); } dfs(1,0); dp(1,0); printf("%lld\n",ans); return 0; }
C++(g++ 7.5.0) 解法, 执行用时: 509ms, 内存消耗: 79808K, 提交时间: 2023-06-23 20:35:38
#include<bits/stdc++.h> using namespace std; using ll=long long; using ul=unsigned long long; using pr=pair<int,int>; mt19937_64 rg(random_device{}()); const int N=5e5+5,M=1e9+7; int n,f[N][55],c[N],sz[N]; int hd[N],ed[N],to[N],w[N]; vector<int>lk[N]; ll ans; void dp(int x,int y,int k){ int i;sz[x]+=sz[y]*k; for(i=1;i<=50;++i) if(i>=c[x])f[x][c[x]]+=f[y][i]*k; else f[x][i]+=f[y][i]*k; } void dfs1(int x,int pr){ int i,y;f[x][c[x]]=sz[x]=1; for(i=hd[x];i;i=to[i]) if((y=ed[i])!=pr) dfs1(y,x),dp(x,y,1); } ll Sum(int x){ ll res=0; for(int i=1;i<=50;++i) res+=i*f[x][i]; return res; } void dfs2(int x,int pr){ int i,y; for(i=hd[x];i;i=to[i]) if((y=ed[i])!=pr){ dp(x,y,-1),dp(y,x,1); dfs2(y,x),dp(y,x,-1); ans+=(Sum(x)*sz[y]+Sum(y)*sz[x])*w[i]; dp(x,y,1); } } int main(){ ios::sync_with_stdio(false); int i,j,k,l,r,x,y; for(i=1,cin>>n;i<=n;++i)cin>>c[i]; for(i=1;i<n;++i){ cin>>x>>y>>k; to[i+i]=hd[x],ed[hd[x]=i+i]=y; to[i+i+1]=hd[y],ed[hd[y]=i+i+1]=x; w[i+i]=w[i+i+1]=k; }dfs1(1,0),dfs2(1,0); printf("%lld\n",ans); return 0; }