先用kruskal处理出一个最小生成树

对于非树边,倍增找出两端点间的最大边权-1就是答案

对于树边,如果它能被替代,就要有一条非树边,两端点在树上的路径覆盖了这条树边,而且边权不大于这条树边

这里可以树剖来做,但是不想用..

如果先把非树边从小到大排序然后去覆盖树边,那么一条树边只需要被覆盖一次

所以可以用一个并查集来把父子边被覆盖的点合到一起,在合并之前记下来这次覆盖的边权,下次再覆盖的时候直接跳过去就可以

 #include<bits/stdc++.h>
#define pa pair<int,int>
#define CLR(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef long long ll;
const int maxn=2e5+,inf=1e9+; inline ll rd(){
ll x=;char c=getchar();int neg=;
while(c<''||c>''){if(c=='-') neg=-;c=getchar();}
while(c>=''&&c<='') x=x*+c-'',c=getchar();
return x*neg;
} struct Edge{
int a,b,l,ne;
bool used;
}eg[maxn],eg2[maxn*];
int egh[maxn],ect;
int N,M,fa[maxn][],bf[maxn],bm[maxn],ma[maxn][],dep[maxn];
int ans[maxn]; inline int getf(int x){return bf[x]==x?x:bf[x]=getf(bf[x]);}
inline bool cmp(Edge a,Edge b){return a.l<b.l;}
inline void adeg(int a,int b,int c){
eg2[++ect].b=b;eg2[ect].ne=egh[a];
eg2[ect].l=c,egh[a]=ect;
} void dfs(int x){
// printf("!!%d %d %d\n",x,fa[x][0],ma[x][0]);
for(int i=;fa[x][i]&&fa[fa[x][i]];i++)
fa[x][i+]=fa[fa[x][i]][i],ma[x][i+]=max(ma[x][i],ma[fa[x][i]][i]);
for(int i=egh[x];i;i=eg2[i].ne){
int b=eg2[i].b;
if(b==fa[x][]) continue;
ma[b][]=eg2[i].l;
fa[b][]=x;dep[b]=dep[x]+;
dfs(b);
}
} int lca(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int re=;
for(int i=log2(dep[x]-dep[y]);i>=&&dep[x]!=dep[y];i--){
if(fa[x][i]&&dep[fa[x][i]]>=dep[y])
re=max(re,ma[x][i]),x=fa[x][i];
}
if(x==y) return re;
for(int i=log2(dep[x]);i>=;i--){
if(fa[x][i]!=fa[y][i])
re=max(re,max(ma[x][i],ma[y][i])),x=fa[x][i],y=fa[y][i];
}
return max(re,max(ma[x][],ma[y][]));
} int main(){
//freopen("","r",stdin);
int i,j,k;
N=rd(),M=rd();
for(i=;i<=M;i++){
eg[i].a=rd(),eg[i].b=rd(),eg[i].l=rd();
eg[i].ne=i;
}
sort(eg+,eg+M+,cmp);
for(i=;i<=N;i++) bf[i]=i;
for(i=,j=;i<=M&&j<N-;i++){
int a=getf(eg[i].a),b=getf(eg[i].b);
if(a!=b){
bf[a]=b;
adeg(eg[i].a,eg[i].b,eg[i].l);
adeg(eg[i].b,eg[i].a,eg[i].l);
eg[i].l=inf;eg[i].used=;
j++;
}
}
dep[]=;dfs();
sort(eg+,eg+M+,cmp);
for(i=;i<=N;i++) bf[i]=i,bm[i]=inf;
for(i=;i<=M;i++){
if(eg[i].used) continue;
int a=getf(eg[i].a),b=getf(eg[i].b);
while(a!=b){
if(dep[a]<dep[b]) swap(a,b);
int bb=getf(fa[a][]);
bf[a]=bb,bm[a]=eg[i].l;
a=bb;
}
}
for(i=;i<=M;i++){
if(eg[i].used){
int a=eg[i].a,b=eg[i].b;
if(dep[a]<dep[b]) swap(a,b);
// a=getf(a),b=getf(b);
if(bm[a]<inf) ans[eg[i].ne]=bm[a]-;
else ans[eg[i].ne]=-;
}else{
ans[eg[i].ne]=lca(eg[i].a,eg[i].b)-;
}
}
for(i=;i<=M;i++)
printf("%d ",ans[i]);
return ;
}

cf827D Best Edge Weight (kruskal+倍增lca+并查集)的更多相关文章

  1. 【CodeForces】827 D. Best Edge Weight 最小生成树+倍增LCA+并查集

    [题目]D. Best Edge Weight [题意]给定n个点m条边的带边权无向连通图,对每条边求最大边权,满足其他边权不变的前提下图的任意最小生成树都经过它.n,m<=2*10^5,1&l ...

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

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

  3. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

  4. BZOJ 4144 Dijkstra+Kruskal+倍增LCA

    思路: 先把所有的加油站 push进按weight排序的优先队列里 对于每个不是加油站的点 找到到它的点的最短路以及它来源的加油站 如果x和y有边 且x和y加油站的来源不一样 则它可以连边 跑一边Kr ...

  5. BZOJ 3732 Network Kruskal+倍增LCA

    题目大意:给定一个n个点m条边的无向连通图.k次询问两点之间全部路径中最长边的最小值 NOIP2013 货车运输.差点儿就是原题...仅仅只是最小边最大改成了最大边最小.. . 首先看到最大值最小第一 ...

  6. CF827D Best Edge Weight 题解

    题意: 给定一个点数为 n,边数为 m,权值不超过 \(10^9\) 的带权连通图,没有自环与重边. 现在要求对于每一条边求出,这条边的边权最大为多少时,它还能出现在所有可能的最小生成树上,如果对于任 ...

  7. HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...

  8. [学习笔记]kruskal重构树 && 并查集重构树

    Kruskal 重构树 [您有新的未分配科技点][BZOJ3545&BZOJ3551]克鲁斯卡尔重构树 kruskal是一个性质优秀的算法 加入的边是越来越劣的 科学家们借这个特点尝试搞一点事 ...

  9. CF1253F Cheap Robot(神奇思路,图论,最短路,最小生成树/Kruskal 重构树/并查集)

    神仙题. 先考虑平方级别的暴力怎么做. 明显答案有单调性,先二分 \(c\). 先最短路预处理 \(dis_u\) 表示 \(u\) 到离它最近的充电站的距离(一开始把 \(1\) 到 \(k\) 全 ...

随机推荐

  1. core_cm4_simd.h文件是干嘛的?

    core_cm4_simd.h文件用于simd指令,即单指令多数据流,这个只有ARMv7架构才有,Cortex m3 m4 m7是ARMv7架构,而Cortex m0 m1是没有的. 所以,在新建Co ...

  2. TomCat 再次发布我的程序

    打包成.war的步骤就不说了,之后的配置和上一次的不一样. 在Tomcat的conf下的server.xml文件中,重新配置如下 <Service name="xfwweb" ...

  3. LInux下设置账号有效时间 以及 修改用户名(同时修改用户组名和家目录)

    在linux系统中,默认创建的用户的有效期限都是永久的,但有时候,我们需要对某些用户的有效期限做个限定!比如:公司给客户开的ftp账号,用于客户下载新闻稿件的.这个账号是有时间限制的,因为是付费的.合 ...

  4. Jenkins新建项目中源码管理Repository URL使用Git报错:Failed to connect to repository : Command "git ls-remote -h......

    之前部署了Gitlab+Gerrit+Jenkins持续集成环境,但在Jenkins中新建项目的源码管理"Repository URL"中添加git地址环节出现了问题,信息为&qu ...

  5. 安装Visual Studio2013

    安装Visual Studio2013现在官网下载在选择安装的可选功能这里,大家可以根据自己需要勾选,也可以默认全选.这里有个小功能,把鼠标放在文字上,会弹出各个功能的详细描述.选择四个常用的功能,另 ...

  6. 《Linux内核设计与实现》 第十八章学习笔记

    调  试 一.准备开始 一个bug 一个藏匿bug的内核版本 相关内核代码的知识和运气 知道这个bug最早出现在哪个内核版本中. 1.想要成功进行调试: 让这些错误重现 抽象出问题 从代码中搜索 二. ...

  7. 11-Python3从入门到实战—基础之生成器和迭代器

    Python从入门到实战系列--目录 切片 Python提供切片(Slice)操作符用来获取列表.元组等数据中的部分元素:如,读取列表 list[m:n]:表示获取m-n区间的元素 list[m:n: ...

  8. vue js 在组件中对数组使用splice() 遇到的坑。。。

    遇到的问题: 用el-dialog写了个子组件 要实现在子组件中增删数据 点击确定后把值返回给父组件 父组件在每次点开子组件时都会把自己的值传进去. //父组件传值 this.$refs.transf ...

  9. 博客用Markdown编辑器插入视频

    要展示一些App的效果用或者更方便地展示工具的操作,可以使用视频. 以下有两种方式可以在博客中插入视频 第一种 此方法适用于插入来源优酷的视频或者你自己录制了视频上传到优酷,这种方法的好处是可以插入时 ...

  10. #Leetcode# 788. Rotated Digits

    https://leetcode.com/problems/rotated-digits/ X is a good number if after rotating each digit indivi ...