CodeForces - 1401D - Maximum Distributed Tree (贪心 + 树上dfs)

简介: 笔记

Maximum Distributed Tree


题意

为一棵树的边添加权值 要求如下


1.权值大于 0

2.所有边权值之积等于 k

3.边权值中 1的个数尽可能少


k 以质因数分解的形式给出6.png


思路

其实这题我们仔细想一下应该可以知道 使经过次数越多的边赋以越大的值可以使得最后结果越大 那么怎么求一条边经过了多少次呢


设 u为 v 的父亲节点siz[v] 表示 以v 为根的子树中节点的数量 那么siz[v]∗(n−siz[v]) 即为经过 u − v这条边的次数


最后讨论一下边的条数和k 的质因数数量的关系即可


若质因数数量小于边的数量 则多出来的边权值取1


否则 从大到小将质因数分配给每一个边


代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define mod 1000000007
#define endl '\n'
using namespace std;
typedef  long long LL;
typedef pair<int, int>PII;
inline LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
inline LL lowbit(LL x) { return x & -x; }
const int N = 100010;
LL n, m;
vector<LL>v[N];
LL prime[N];
LL siz[N], tot[N];
int cnt = 0;
bool cmp(LL a, LL b) {
  return a > b;
}
void dfs(LL u, LL fa) {
  siz[u] = 1;
  for (LL i = 0; i < v[u].size(); ++i) {
    LL j = v[u][i];
    if (j != fa) {
      dfs(j, u);
      siz[u] += siz[j];
      tot[++cnt] = siz[j] * (n - siz[j]);
    }
  }
}
void init() {
  for (int i = 0; i <= n + 1; ++i) {
    v[i].clear();
  }
  for (int i = 0; i <= m + 1; ++i) {
    prime[i] = 0;
  }
  cnt = 0;
}
void solve() {
  cin >> n;
  for (LL i = 1; i <= n - 1; ++i) {
    LL a, b; scanf("%lld%lld", &a, &b);
    v[a].push_back(b);
    v[b].push_back(a);
  }
  dfs(1, 0);
  cin >> m;
  for (LL i = 1; i <= m; ++i)
    scanf("%lld", &prime[i]);
  sort(prime + 1, prime + m + 1, cmp);
  sort(tot + 1, tot + cnt + 1, cmp);
  LL res = 0;
  if (m < cnt) { //质因数少 降序排列 将大的质因数优先给次数多的边 剩余的边的用1
    sort(prime + 1, prime + m + 1, cmp);
    sort(tot + 1, tot + cnt + 1, cmp);
    for (int i = 1; i <= m; ++i) {
      res = (res + tot[i] * prime[i] % mod) % mod;
    }
    for(int i = m + 1;i <= cnt;++i){
      res = (res + tot[i]) % mod;
    }
  }
  else { //质因数多 将多出的质因数合并成一个给出现次数最多的边
    sort(prime + 1, prime + m + 1);
    sort(tot + 1, tot + 1 + cnt);
    LL t = 1;
    for (int i = cnt; i <= m; ++i) {
      t = t * prime[i] % mod;
    }
    prime[cnt] = t;
    for (int i = 1; i <= cnt; ++i) {
      res = (res + prime[i] * tot[i] % mod) % mod;
    }
  }
  cout << res % mod << endl;
  init();
}
int main() {
  int t; cin >> t;
  while(t--)
    solve();
  return 0;
}


目录
打赏
0
0
0
0
1
分享
相关文章
UVa872 - Ordering(拓扑排序)
UVa872 - Ordering(拓扑排序)
72 0
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密(二)
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密
172 0
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密(二)
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密(三)
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密
146 0
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密(三)
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密(一)
【基础算法】关于图论中最小生成树(Minimum Spanning Tree)那些不可告人的秘密
260 0
【1094】The Largest Generation (树DFS-水题)
基础题。 这类题也是直接DFS,不是像上次的【1079】&【1090】供应树DFS一样是到了叶子结点就进行“更新/结算”类型,这题直接利用DFS统计每层的结点个数即可。
113 0
【1115】Counting Nodes in a BST (30分)【BST建树 DFS】
【1115】Counting Nodes in a BST (30分)【BST建树 DFS】 【1115】Counting Nodes in a BST (30分)【BST建树 DFS】
126 0
【LeetCode-面试算法经典-Java实现】【111-Minimum Depth of Binary Tree(二叉树的最小深度)】
原题   Given a binary tree, find its minimum depth.   The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.  题目大意   给定一棵两叉树求树的最小深度。
1403 0
1004. Counting Leaves (30) 树的dfs
#include #include #include using namespace std; //大意:统计每一层叶子结点的个数 并输出 //根节点id固定为01 //思路:树的模拟套路 vector v[100]...
895 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等