知识大全 次小生成树 Tree-LCA的位运算

Posted

篇首语:无限相信书籍的力量,是我的教育信仰的真谛之一。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 次小生成树 Tree-LCA的位运算相关的知识,希望对你有一定的参考价值。

次小生成树 Tree-LCA的位运算  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  关于次小生成树 Tree LCA的位运算我们有实例!

  小 C 最近学了很多最小生成树的算法 Prim 算法 Kurskal 算法 消圈算法 等等 正当小 C 洋洋得意之时 小 P 又来泼小 C 冷水了 小 P 说 让小 C 求出一 个无向图的次小生成树 而且这个次小生成树还得是严格次小的 也就是说 如果最小生成树选择的边集是 EM 严格次小生成树选择的边集是 ES 那么 需要满足 (value(e) 表示边 e的权值) 这下小 C 蒙了 他找到了你 希望你帮他解决这个问题

  Input

  第一行包含两个整数N 和M 表示无向图的点数与边数 接下来 M行 每行 个数x y z 表示 点 x 和点y之间有一条边 边的权值 为z

  Output

  包含一行 仅一个数 表示严格次小生成树的边权和 (数 据保证必定存在严格次小生成树)

  Sample Input

  

  

  

  

  

  

  

  Sample Output

  

  HINT

  数据中无向图无自环;

   % 的数据N≤ M≤ ;

   % 的数据N≤ M≤ ;

   % 的数据N≤ M≤ 边权值非负且不超过 ^

  

  Source

  这题的关键就在于求Lca 记录路径上的最小与严格次小值

  用f[i][j]表示i的第 ^j个儿子( 表示 不存在)

  那么f[i][j]=f[ f[i][ j ] ][j ]

  dp[i][j]和dp [i][j]表示点i到f[i][j]的最小和严格次小值(不存在= ) 那么只需特判即可

  [cpp]

  int lca(int x int y int &nowdp int &nowdp )

  

  if (deep[x]<deep[y]) swap(x y);

  int t=deep[x] deep[y]; //差的数量

  for (int i= ;t;i++)

  if (t&bin[i]) //转化为位运算 bin[i]表示 <<i 把t看成 进制

  

  x=f[x][i];

  t =bin[i];

  

  int i=Li ; //Li 表示 最高存到 ^(Li )个父亲

  while (x^y) //x和y不相等时

  

  while (f[x][i]==f[y][i]&&i) i ; //当i== 时只能向上跳

  x=f[x][i];y=f[y][i];

  

  

  程序

  [cpp]

  #include<cstdio>

  #include<cstdlib>

  #include<cstring>

  #include<iostream>

  #include<algorithm>

  #include<functional>

  using namespace std;

  #define MAXN ( + )

  #define MAXM ( + )

  #define Li ( )

  #define INF ( )

  int edge[MAXM] pre[MAXM] weight[MAXM] next[MAXM] size= ;

  int addedge(int u int v int w)

  

  edge[++size]=v;

  weight[size]=w;

  next[size]=pre[u];

  pre[u]=size;

  

  int addedge (int u int v int w)

  

  addedge(u v w);

  addedge(v u w);

  

  int f[MAXN][Li]= dp[MAXN][Li]= dp [MAXN][Li]= deep[MAXN] n m;

  struct E

  

  int u v w;

  friend bool operator<(E a E b)return a w<b w;

  e[MAXM];

  bool b[MAXM] vis[MAXN];

  int queue[MAXN] head tail;

  void bfs()

  

  memset(vis sizeof(vis));

  head=tail= ;queue[ ]= ;vis[ ]= ;deep[ ]= ;

  while (head<=tail)

  

  int &u=queue[head];

  if (u!= )

  

  for (int i= ;i< ;i++)

  

  if (f[u][i ])

  

  f[u][i]=f[f[u][i ]][i ];

  

  if (f[u][i]== ) break;

  if (f[u][i])

  

  dp[u][i]=max(dp[u][i ] dp[f[u][i ]][i ]);

  

  if (i== )

  

  if (dp[u][ ]!=dp[f[u][ ]][ ]) dp [u][ ]=min(dp[u][ ] dp[f[u][ ]][ ]);

  else dp [u][ ]= ;

  

  else

  

  dp [u][i]=max(dp [u][i ] dp [f[u][i ]][i ]);

  if (dp[u][i ]!=dp[f[u][i ]][i ]) dp [u][i]=max(dp [u][i] min(dp[u][i ] dp[f[u][i ]][i ]));

  

  

  

  for (int p=pre[u];p;p=next[p])

  

  int &v=edge[p];

  if (!vis[v])

  

  queue[++tail]=v;

  vis[v]= ;deep[v]=deep[u]+ ;

  f[v][ ]=u;dp[v][ ]=weight[p];dp [v][ ]= ;

  

  

  head++;

  

  

  int bin[Li];

  void check(int &nowdp int &nowdp int c)

  

  if (c<=nowdp ) return;

  else if (nowdp <c&&c<nowdp) nowdp =c;

  else if (c==nowdp) return;

  else if (nowdp<c) nowdp =nowdp;nowdp=c;

  

  int lca(int x int y int &nowdp int &nowdp )

  

  nowdp=nowdp = ;

  if (deep[x]<deep[y]) swap(x y);

  int t=deep[x] deep[y];

  for (int i= ;t;i++)

  if (t&bin[i])

  

  check(nowdp nowdp dp[x][i]);

  check(nowdp nowdp dp [x][i]);

  x=f[x][i];

  t =bin[i];

  

  int i=Li ;

  while (x^y)

  

  while (f[x][i]==f[y][i]&&i) i ;

  check(nowdp nowdp dp[x][i]);

  check(nowdp nowdp dp [x][i]);

  check(nowdp nowdp dp[y][i]);

  check(nowdp nowdp dp [y][i]);

  x=f[x][i];y=f[y][i];

  

  

  int father[MAXN];

  long long sum_edge= ;

  int getfather(int x)

  

  if (father[x]==x) return x;

  father[x]=getfather(father[x]);

  return father[x];

  

  void union (int x int y)

  

  father[father[x]]=father[father[y]];

  

  int main()

  

  scanf( %d%d &n &m);

  for (int i= ;i<=n;i++) father[i]=i;

  memset(b sizeof(b));

  memset(next sizeof(next));

  for (int i= ;i<Li;i++) bin[i]= <<i;

  for (int i= ;i<=m;i++)

  

  scanf( %d%d%d &e[i] u &e[i] v &e[i] w);

  

  sort(e+ e+ +m);

  for (int i= ;i<=m;i++)

  

  if (getfather(e[i] u)!=getfather(e[i] v)) union (e[i] u e[i] v);addedge (e[i] u e[i] v e[i] w);sum_edge+=e[i] w;

  else b[i]= ;

  

  bfs();

  long long mindec= ;

  for (int i= ;i<=m;i++)

  if (b[i])

  

  int nowdp nowdp ;

  lca(e[i] u e[i] v nowdp nowdp );

  if (nowdp==e[i] w) nowdp=nowdp ;

  if (nowdp== ) continue;

  if (mindec== ||mindec>e[i] w nowdp) mindec=e[i] w nowdp;

  

  printf( %lld\\n sum_edge+mindec);

  return ;

cha138/Article/program/Java/hx/201311/26453

相关参考

中国超级计算机运算速度重返世界之巅。中国国防科学技术大学研制的“__”以每秒33.86千万亿次的浮点运算速度,成为

中国超级计算机运算速度重返世界之巅。中国国防科学技术大学研制的“_____”以每秒33.86千万亿次的浮点运算速度,成为全球最快的超级计算机。A、泰坦B、天河二号C、红河D、天河一号答案:B解析:国际

知识大全 进制中的位权是什么意思

进制中的位权是什么意思?最好举几个例子1、在各种数制(无论是二进制,十进制、十六进制等)中,各位数字所表示值的大小不仅与该数字本身的大小有关,还与该数字所在的位置有关,我们称这关系为数的位权。2、拿十

知识大全 Delphi的位操作以及嵌入式汇编[1]

Delphi的位操作以及嵌入式汇编[1]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  每个学习

知识大全 Delphi的位操作以及嵌入式汇编[2]

Delphi的位操作以及嵌入式汇编[2]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  *Del

知识大全 Delphi的位操作以及嵌入式汇编[3]

Delphi的位操作以及嵌入式汇编[3]  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  一个把字

某儿童去过几次游乐场,就能画出具体的路线图。这名儿童的认知发展达到了下列哪一阶段

某儿童去过几次游乐场,就能画出具体的路线图。这名儿童的认知发展达到了下列哪一阶段?A、感知运动阶段B、前运算阶段C、具体运算阶段D、形式运算阶段答案:C解析:具体运算阶段的儿童在分类、数字处理、时间和

“改革开放实践的不断深入发展,引起了我国人民思想上的巨大解放和观念上的不断更新,封闭、保守、狭隘的小生产观念正在被打破

“改革开放实践的不断深入发展,引起了我国人民思想上的巨大解放和观念上的不断更新,封闭、保守、狭隘的小生产观念正在被打破,逐渐被开放、进取、开拓、创新等观念所代替。”这一事实说明_____。A、开放、进

知识大全 数据结构之单链表基本运算的实现[5]

  ()按值查找  单链表的按值查找是在线性表存在的情况下查找值为x的数据元素若成功返回首次出现的值为x的那个元素所在结点的指针;否则未找到值为x的数据元素返回NULL表示查找失败  算法思路从链表的

知识大全 数据结构之顺序表上基本运算的实现[13]

  本算法中时间主要消耗在for循环上的元素与元素之间的交换该循环的循环次数为n/次所以其时间复杂度为O(n)  【例】有顺序表A和B其元素均按从小到大的升序排列编写一个算法将它们合并成一个顺序表C要

知识大全 二叉树的遍历

遍历概念  所谓遍历(Traversal)是指沿着某条搜索路线依次对树中每个结点均做一次且仅做一次访问访问结点所做的操作依赖于具体的应用问题  遍历是二叉树上最重要的运算之一是二叉树上进行其它运算之基