CF1401D Maximum Distributed Tree(贪心)
题意:
给出一棵树和一个大数k,请你给这棵树上的每条边分配一个边权,使得这棵树上的节点两两之间的路径总和最大,同时边权中1的数量尽可能少,同时所有边权的乘积等于k。
题解:
一遍DFS处理出每条边对答案的贡献,将边按照贡献从小到大排序,优先把大的因子给贡献大的边。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+100; const int mod=1e9+7; int t; int n; int m; ll p[maxn]; int size[maxn]; vector<int> g[maxn]; void dfs (int u,int pre) { size[u]=1; for (int v:g[u]) { if (v==pre) continue; dfs(v,u); size[u]+=size[v]; } } struct node { ll x,y; bool operator < (const node &r) const { return (ll)x*y>(ll)r.x*r.y; } }Node[maxn]; bool cmp (int x,int y) { return x>y; } int main () { scanf("%d",&t); while (t--) { scanf("%d",&n); for (int i=1;i<=n;i++) g[i].clear(); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); g[x].push_back(y); g[y].push_back(x); } scanf("%d",&m); for (int i=1;i<=m;i++) scanf("%lld",p+i); sort(p+1,p+m+1,cmp); dfs(1,0); int tot=0; for (int i=2;i<=n;i++) { //printf("%lld %lld\n",n-size[i],size[i]); Node[++tot]={(ll)n-size[i],(ll)size[i]}; } sort(Node+1,Node+tot+1); ll ans=0; if (n-1>=m) { for (int i=1;i<=m;i++) { ans+=(ll)p[i]*Node[i].x*Node[i].y; ans%=mod; } for (int i=m+1;i<=tot;i++) { ans+=(ll)Node[i].x*Node[i].y; ans%=mod; } } else { ll tt=1; //printf("1\n"); //m>=n for (int i=1;i<=(m-n+2);i++) { tt*=p[i]; tt%=mod; } //printf("%lld\n",tt); ans+=(ll)tt*Node[1].x%mod*Node[1].y; //printf("%lld\n",ans); ans%=mod; for (int i=m-n+3;i<=m;i++) { ans+=(ll)p[i]*Node[i-(m-n+1)].x*Node[i-(m-n+1)].y; ans%=mod; } } printf("%lld\n",ans); } }