[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;
}
/**
**/




目录
相关文章
|
9月前
2022天梯赛三月冲刺——PAT (Advanced Level)1013 Battle Over Cities (并查集找连通块)
2022天梯赛三月冲刺——PAT (Advanced Level)1013 Battle Over Cities (并查集找连通块)
51 0
|
11月前
|
C++ 网络架构
【PAT甲级 - C++题解】1013 Battle Over Cities
【PAT甲级 - C++题解】1013 Battle Over Cities
47 1
|
算法
聪明的KK【ACM】
聪明的KK【ACM】
71 0
|
BI
2022年牛客多校第2场 J . Link with Arithmetic Progression (三分+枚举)
2022年牛客多校第2场 J . Link with Arithmetic Progression (三分+枚举)
94 0
UPC组队赛第三场——G: The Famous ICPC Team Again (主席树)
UPC组队赛第三场——G: The Famous ICPC Team Again (主席树)
74 0
AtCoder Beginner Contest 223 D - Restricted Permutation(建图 思维 构造 拓扑排序)
AtCoder Beginner Contest 223 D - Restricted Permutation(建图 思维 构造 拓扑排序)
88 0
|
存储
UPC组队第三场——K: A Famous Grid (BFS+细节)
UPC组队第三场——K: A Famous Grid (BFS+细节)
61 0
UPC组队第三场——K: A Famous Grid (BFS+细节)
2020 ICPC Asia Taipei-Hsinchu Site Programming Contest H. Optimization for UltraNet (二分+最小生成树+算贡献)
2020 ICPC Asia Taipei-Hsinchu Site Programming Contest H. Optimization for UltraNet (二分+最小生成树+算贡献)
103 0
|
机器学习/深度学习
[Nowcoder | UPC] 2021年度训练联盟热身训练赛第六场 Hopscotch | 最短路 bfs
题目描述 There’s a new art installation in town, and it inspires you… to play a childish game. The art installation consists of a floor with an n×n matrix of square tiles. Each tile holds a single number from 1 to k. You want to play hopscotch on it.
93 0
|
人工智能 Java
HDU - 2018杭电ACM集训队单人排位赛 - 2 - Problem C. Team Match
HDU - 2018杭电ACM集训队单人排位赛 - 2 - Problem C. Team Match
118 0