【题目】D. Best Edge Weight

【题意】给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它。n,m<=2*10^5,1<=wi<=10^9。

【算法】最小生成树+倍增LCA+并查集

【题解】首先求出图的一个最小生成树M,则所有边分成树边和非树边。

一、对于非树边(u,v),假设u和v在最小生成树M上的路径的最大边权是Max。要保证这条边在最小生成树上,只要w(u,v)=Max-1。

下面证明w(u,v)=Max-1时,一定在任意最小生成树上。

证明:假设另一个最小生成树OM不包含(u,v),那么u和v在最小生成树OM上的路径的所有边权<=Max-1,按照kruscal算法从小到大加边的情况,(u,v)一定会被最小生成树OM首先连通,故M不是最小生成树,矛盾。

二、对于树边(u,v),假设所有在最小生成树M上的路径经过它的非树边的最小边权是Min。要保证这条边在最小生成树M上(不会被替换),只要w(u,v)=Min-1。

证明:如果(u,v)已经是所有它所在的环中的最小边,那么一定会先被连通。

最后,我们需要解决问题是:找到一个最小生成树,对于每条非树边找到路径最大值,然后给路径贡献最小值标记,最后统计树边的答案。

这用树链剖分+线段树是很容易实现的,还可以用线段树合并(权值),不过最简便的是倍增+并查集。

倍增:记录路径最大值,即可回答第一个询问。

并查集:非树边从小到大排序后依次处理,标记到的边就是最小值了,处理完后用并查集并起来以后不再处理(初始fa[i]=i),即每个点的父亲指向祖先中最近的未处理点(边),类似安全路经Travel

注意先kruscal后按照生成树边来dfs建树。答案可能有0。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. const int maxn=;
  6. struct edge{int id,u,v,w,from;}e[maxn*],ed[maxn*];
  7. int n,m,first[maxn],tot,f[maxn][],g[maxn][],deep[maxn],fa[maxn],a[maxn],E[maxn],ans[maxn];
  8. void insert(int u,int v,int w,int id){tot++;e[tot].id=id;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
  9. bool cmp(edge a,edge b){return a.w<b.w||(a.w==b.w&&a.id<b.id);}
  10. int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
  11. void dfs(int x,int fa){
  12. for(int i=;(<<i)<=deep[x];i++){
  13. f[x][i]=f[f[x][i-]][i-];
  14. g[x][i]=max(g[x][i-],g[f[x][i-]][i-]);
  15. }
  16. for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa&&a[e[i].id]){
  17. deep[e[i].v]=deep[x]+;
  18. f[e[i].v][]=x;
  19. g[e[i].v][]=e[i].w;
  20. E[e[i].v]=e[i].id;
  21. dfs(e[i].v,x);
  22. }
  23. }
  24. int lca(int x,int y){
  25. if(deep[x]<deep[y])swap(x,y);
  26. int ans=,d=deep[x]-deep[y];
  27. for(int i=;i<=;i++)if(d&(<<i))ans=max(ans,g[x][i]),x=f[x][i];
  28. if(x==y)return ans;
  29. for(int i=;i>=;i--)if((<<i)<=deep[x]&&f[x][i]!=f[y][i]){
  30. ans=max(ans,max(g[x][i],g[y][i]));
  31. x=f[x][i];y=f[y][i];
  32. }
  33. return max(ans,max(g[x][],g[y][]));
  34. }
  35. int main(){
  36. scanf("%d%d",&n,&m);
  37. for(int i=;i<=m;i++){
  38. scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w);//
  39. ed[i].id=i;
  40. }
  41. sort(ed+,ed+m+,cmp);
  42. for(int i=;i<=n;i++)fa[i]=i;
  43. for(int i=;i<=m;i++){
  44. int x=find(ed[i].u),y=find(ed[i].v);
  45. if(x!=y){a[ed[i].id]=;fa[x]=y;}
  46. }
  47. for(int i=;i<=m;i++)insert(ed[i].u,ed[i].v,ed[i].w,ed[i].id),insert(ed[i].v,ed[i].u,ed[i].w,ed[i].id);
  48. dfs(,);
  49. for(int i=;i<=n;i++)fa[i]=i;
  50. memset(ans,-,sizeof(ans));//
  51. for(int i=;i<=m;i++)if(!a[ed[i].id]){
  52. int x=find(ed[i].u),y=find(ed[i].v);
  53. ans[ed[i].id]=lca(ed[i].u,ed[i].v)-;
  54. while(x!=y){
  55. if(deep[x]<deep[y])swap(x,y);
  56. ans[E[x]]=ed[i].w-;
  57. x=fa[x]=find(f[x][]);//
  58. }
  59. }
  60. for(int i=;i<=m;i++)printf("%d ",ans[i]);
  61. return ;
  62. }

【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集的更多相关文章

  1. cf827D Best Edge Weight (kruskal+倍增lca+并查集)

    先用kruskal处理出一个最小生成树 对于非树边,倍增找出两端点间的最大边权-1就是答案 对于树边,如果它能被替代,就要有一条非树边,两端点在树上的路径覆盖了这条树边,而且边权不大于这条树边 这里可 ...

  2. 【BZOJ-3910】火车 倍增LCA + 并查集

    3910: 火车 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 262  Solved: 90[Submit][Status][Discuss] De ...

  3. 训练指南 UVA - 11354(最小生成树 + 倍增LCA)

    layout: post title: 训练指南 UVA - 11354(最小生成树 + 倍增LCA) author: "luowentaoaa" catalog: true ma ...

  4. 【bzoj3732】Network 最小生成树+倍增LCA

    题目描述 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 & ...

  5. 【bzoj4242】水壶 BFS+最小生成树+倍增LCA

    题目描述 JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有P个,编号为1...P. JOI君只能进入 ...

  6. BZOJ 3732 Network —— 最小生成树 + 倍增LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 <= N <= 15, ...

  7. BFS+最小生成树+倍增+LCA【bzoj】4242 水壶

    [bzoj4242 水壶] Description JOI君所居住的IOI市以一年四季都十分炎热著称. IOI市是一个被分成纵H*横W块区域的长方形,每个区域都是建筑物.原野.墙壁之一.建筑物的区域有 ...

  8. 2018.09.24 bzoj1016: [JSOI2008]最小生成树计数(并查集+搜索)

    传送门 正解是并查集+矩阵树定理. 但由于数据范围小搜索也可以过. 我们需要知道最小生成树的两个性质: 不同的最小生成树中,每种权值的边出现的个数是确定的 不同的生成树中,某一种权值的边连接完成后,形 ...

  9. Codeforces Round #363 (Div. 2) D. Fix a Tree —— 并查集

    题目链接:http://codeforces.com/contest/699/problem/D D. Fix a Tree time limit per test 2 seconds memory ...

随机推荐

  1. 类的static成员变量和成员函数能被继承吗

    1.   父类的static变量和函数在派生类中依然可用,但是受访问性控制(比如,父类的private域中的就不可访问),而且对static变量来说,派生类和父类中的static变量是共用空间的,这点 ...

  2. emacs编译整个emacs.d目录

    $emacs 在emacs查看里面,输入: C-u M-x byte-recompile-directory 然后输入 ~/.emacs.d 即可.

  3. linux虚拟机发邮件给163邮件

    配置/etc/mail.rc文件 set from=xxxxxxxx@163.com smtp=smtp.163.com set smtp-auth-user=yinhuanyi_cn@163.com ...

  4. openssl 基本加密

    openssl命令行工具详解(openssl的命令众多,请酌情处理与记忆) 在命令行输入:openssl asdf,可以显示openssl的命令说明   1:Standard commands(标准命 ...

  5. 基于图形学混色问题OpenGl的收获

    void myDisplay(void) {glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_B ...

  6. Struts2文件的上传和下载实现

    <一>简述: Struts2的文件上传其实也是通过拦截器来实现的,只是该拦截器定义为默认拦截器了,所以不用自己去手工配置,<interceptor name="fileUp ...

  7. vue render & array of components & vue for & vue-jsx

    vue render & array of components & vue for & vue-jsx https://www.cnblogs.com/xgqfrms/p/1 ...

  8. 【C++】深度探索C++对象模型读书笔记--构造函数语义学(The Semantics of constructors)(四)

    成员们的初始化队伍(member Initia 有四种情况必须使用member initialization list: 1. 当初始化一个reference member时: 2. 当初始化一个co ...

  9. 第113天:Ajax跨域请求解决方法

    一.原生JS实现ajax 第一步获得XMLHttpRequest对象 第二步:设置状态监听函数 第三步:open一个连接,true是异步请求 第四部:send一个请求,可以发送一个对象和字符串,不需要 ...

  10. CSS单位-长度

    css中的长度单位有很多,不同的单位在特定的需求下能够有相当不错的表现,随着css3的发布,又有了一些新的单位添加进来,使我们在做前端页面的时候能够有更多的选择,更方便快捷的达到我们预期的效果. 正题 ...