[ICPC 46th Shanghai] Life is a Game 克鲁斯卡尔重构树

简介: 题目大意:给定n个点,m条边,有q个询问每个点有一个(能量值)点权,每条边有一个边权m条边描述为u v w表示有一条u与v相连的边权为w的通路在每一次询问中,给定一个点x和现有的能量值k,每次只能是在当前能量值大于边权的时候到达另一个点,并获取这个点的能量值(路可以重复走),问最终能够获得多大的能量值

题目链接


题目大意:


给定n个点,m条边,有q个询问

每个点有一个(能量值)点权,每条边有一个边权

m条边描述为u v w表示有一条u与v相连的边权为w的通路


在每一次询问中,给定一个点x和现有的能量值k,每次只能是在当前能量值大于边权的时候到达另一个点,并获取这个点的能量值(路可以重复走),问最终能够获得多大的能量值


思路:


克鲁斯卡尔重构树

在建立克鲁斯卡尔重构树的时候,会将边权化为点权来处理并建立成一个堆,而且原先的节点一定是重构树中的 叶子节点 ,除了叶子节点之外的其他点都是原先的边权

在克鲁斯卡尔重构树中,从叶子节点以上到根的路径中,点权一定是单调不减的


所以说给定的节点要是能够直接跳到祖先节点的话,那么说以这个节点为根的子树都能够访问到

所以说在这里可以使用倍增来处理,并且在维护以某节点为根的子树的所有节点的能量值

这样如果说能够跳过去的话,就将能量值的贡献加过去,直到不能跳为止


code:


ll fa[maxn],siz[maxn],a[maxn];
vector<int> gra[maxn];
ll bz[27][maxn],n,m,cnt,q;
struct node {
  int u,v,w;
  friend bool operator<(node a,node b) {
    return a.w < b.w;
  }
  node() {  }
  node(int _u,int _v,int _w) {
    u = _u,v = _v,w = _w;
  }
};
vector<node> vet;
int get(int x) {
  if(x == fa[x]) return x;
  else return fa[x] = get(fa[x]);
}
void init() {
  for(int i=0; i<=n*2; i++) fa[i] = i;//,siz[i] = 1;
}
void kru() {
  sort(vet.begin(),vet.end());
  for(int i=0; i<m; i++) {
    node nd = vet[i];
    int u = nd.u,v = nd.v,w = nd.w;
    int fau = get(u);
    int fav = get(v);
    if(fau != fav) {
      a[++cnt] = w;
      fa[cnt] = fa[fau] = fa[fav] = cnt;
      gra[fau].push_back(cnt);
      gra[cnt].push_back(fau);
      gra[fav].push_back(cnt);
      gra[cnt].push_back(fav);
    }
  }
}
void dfs(int u,int fa) {
  bz[0][u] = fa;
  for(int i=1; i<=20; i++) {
    bz[i][u] = bz[i-1][bz[i-1][u]];
  }
  for(int to:gra[u]) {
    if(to == fa) continue;
    dfs(to,u);
    siz[u] += siz[to];
  }
}
int main() {
  n = read,m = read,q = read;
  init();
  cnt = n;
  for(int i=1; i<=n; i++) siz[i] = read;
  for(int i=1; i<=m; i++) {
    int u = read,v = read,w = read;
    vet.push_back(node {u,v,w});
  }
  kru();
  dfs(cnt,0);
  a[0] = ((1LL<<31)-1);
  for(int i=1; i<=q; i++) {
    ll u = read,s = read;
    ll now = s + siz[u];
    while(u != cnt) {
      int tu = u;
      for(int i=20; i>=0; i--) {
        if(a[bz[i][u]] <= now) u = bz[i][u];
      }
      if(tu == u) break;
      now = siz[u] + s;
    }
//    printf("->>>> %lld\n",now);
        printf("%lld\n",now);
  }
  return 0;
}
/**
**/




目录
相关文章
|
人工智能 Java 大数据
Java程序员真的还有未来吗?如何备战2024春招?并狂拿大厂offer?
Java程序员还有未来吗? 嘿,小伙伴们,你们有没有想过Java程序员还有没有未来? 哈哈,别担心,我这就来给你们答疑解惑! 首先,让我们来看看Java的发展历程。自从Java诞生以来,它就一直是编程界的一颗璀璨明星。从Web应用到企业级应用,再到移动应用,Java无处不在。那么,现在呢?现在,随着人工智能、大数据和云计算的兴起,Java依然发挥着重要的作用。这些领域都需要大量的Java程序员来支持它们的发展。 那么,有人会说:“哎呀,现在出现了那么多新的编程语言和框架,Java程序员会不会被淘汰啊?”哈哈,别担心,Java程序员们!这些新语言和框架的出现并不会让Java消失。相反,它们
364 0
|
11月前
|
SQL 分布式计算 数据库
【YashanDB 知识库】Hive 命令工具 insert 崖山数据库报错
【YashanDB 知识库】Hive 命令工具 insert 崖山数据库报错
|
机器学习/深度学习 算法 计算机视觉
【博士每天一篇文献-算法】持续学习经典算法之LwF: Learning without forgetting
LwF(Learning without Forgetting)是一种机器学习方法,通过知识蒸馏损失来在训练新任务时保留旧任务的知识,无需旧任务数据,有效解决了神经网络学习新任务时可能发生的灾难性遗忘问题。
1392 9
使用京东API接口进行支付结算有哪些注意事项?
使用京东API接口进行支付结算时,需遵守京东开放平台规定,保护用户隐私,关注API接口变化,确保应用合法、完整、可靠,正确使用API对接信息,保持API接口调用成功率,及时整改程序缺陷,结算依据以商家后台系统为准。如需帮助,请私信或评论联系。
|
监控 测试技术 数据安全/隐私保护
Snmp接口测试随记
Snmp接口测试方案,以及使用python开发的工具实现自动化测试。
311 0
|
消息中间件 缓存 NoSQL
记一次蚂蚁金服四面遭虐,面试水太深,过河的渡船你造好了吗?
有道无术,术可成;有术无道,止于道;以术识道,以道御术
|
资源调度 运维 负载均衡
带你读《云原生架构白皮书2022新版》——Serverless(下)
带你读《云原生架构白皮书2022新版》——Serverless(下)
497 57
连续五年!中国唯一!入选Gartner ABI魔力象限!
连续五年!中国唯一!入选Gartner ABI魔力象限!
409 0
|
程序员 C# C++
lpszBlogName C#开发多年中途被迫改行C++但工作中又经常偷偷使用C#的C++程序员
通过AUMID解析出packageFamily,再根据PackageManager解析出安装目录 PackageManager是WinRT的类型,如何在c++中使用WinRT,请参考C++/WinRT 以下代码需要管理员权限才能运行。
168 0
Go --- gin配置swagger
Go --- gin配置swagger
Go --- gin配置swagger

热门文章

最新文章