【XSY2485】MST(最小生成树+倍增lca+并查集)
题面
Description
给定一个nnn个点mmm条边的连通图,保证没有自环和重边。对于每条边求出,在其他边权值不变的情况下,它能取的最大权值,使得这条边在连通图的所有最小生成树上。假如最大权值为无限大,则输出−1-1−1。
Input
第一行两个整数nnn,mmm,表示nnn个点mmm条边
接下来mmm行,每行333个整数xxx,yyy,zzz,表示节点xxx和节点yyy之间有一条长zzz的边。
Output
输出一行mmm个整数,表示每条边的答案
Sample Input
4 4
1 2 2
2 3 2
3 4 2
4 1 3
Sample Output
2 2 2 1
HINT
对于30%30\%30%的数据1≤n≤1031≤n≤10^31≤n≤103,1≤m≤3×1031≤m≤3\times10^31≤m≤3×103
对于100%100\%100%的数据1≤n,m≤2×1051≤n,m≤2\times 10^51≤n,m≤2×105,1≤z≤1091≤z≤10^91≤z≤109
题解
(来自XSY的solution)
先求出图的一棵最小生成树:
对于不在树上的边(x,y)(x,y)(x,y), 它的权值只要小于树上xxx到yyy路径中一条边就可以代替这条边。
对于在树上的边(x,y)(x,y)(x,y),可以先预处理出所有两端在xxx到yyy路径上的不在树上的边的最小值。它的权值一定要小于最小值。
路径maxmaxmax和minminmin都可以用倍增求。
时间复杂度O(nlogn)O(nlogn)O(nlogn)。
代码:
#include<bits/stdc++.h>#define N 200010
#define M127 2139062143using namespace std;struct edge
{int u,v,w,id;
}e[N];int n,m,fa[N],ans[N];
int cnt,head[N],to[N<<1],nxt[N<<1],w[N<<1],id[N<<1];
int f[N][20],maxn[N][20],from[N],d[N];
bool flag[N];void adde(int u,int v,int wi,int idi)
{to[++cnt]=v;w[cnt]=wi;id[cnt]=idi;nxt[cnt]=head[u];head[u]=cnt;
}bool cmp(edge a,edge b)
{return a.w<b.w;
}int find(int x)
{if(fa[x]!=x)return fa[x]=find(fa[x]);return x;
}void dfs(int u)
{for(int i=1;i<=18;i++){f[u][i]=f[f[u][i-1]][i-1];maxn[u][i]=max(maxn[u][i-1],maxn[f[u][i-1]][i-1]);}for(int i=head[u];i;i=nxt[i]) {if(to[i]!=f[u][0]){f[to[i]][0]=u;maxn[to[i]][0]=w[i];from[to[i]]=id[i];d[to[i]]=d[u]+1;dfs(to[i]);}}
}int getMax(int a,int b,int &lca)
{int ans=0;if(d[a]<d[b])swap(a,b);for(int i=18;i>=0;i--){if(d[f[a][i]]>=d[b]){ans=max(ans,maxn[a][i]);a=f[a][i];}}if(a==b){lca=a;return ans;}for(int i=18;i>=0;i--){if(f[a][i]!=f[b][i]){ans=max(ans,maxn[a][i]);ans=max(ans,maxn[b][i]);a=f[a][i],b=f[b][i]; }}lca=f[a][0];return max(ans,max(maxn[a][0],maxn[b][0]));
}void solve(int u,int lca,int wi)
{u=find(u);while(d[u]>d[lca]){ans[from[u]]=min(ans[from[u]],wi-1);fa[u]=find(f[u][0]);u=find(u);}
}int main()
{memset(ans,127,sizeof(ans));scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);e[i].id=i;}sort(e+1,e+m+1,cmp);for(int i=1,tot=0;i<=m;i++){if(tot==n-1)break;int x=find(e[i].u);int y=find(e[i].v);if(x!=y){fa[y]=x;adde(e[i].u,e[i].v,e[i].w,e[i].id);adde(e[i].v,e[i].u,e[i].w,e[i].id);flag[i]=true;tot++;}}dfs(1);for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<=m;i++){if(!flag[i]){int lca;ans[e[i].id]=getMax(e[i].u,e[i].v,lca)-1;solve(e[i].u,lca,e[i].w);solve(e[i].v,lca,e[i].w);}}for(int i=1;i<=m;i++){if(ans[i]==M127)printf("-1 ");else printf("%d ",ans[i]);}return 0;
}
【XSY2485】MST(最小生成树+倍增lca+并查集)相关推荐
- mst算法matlab_基于并查集+Kruskal算法的matlab程序及最小生成树绘图
学了一天最小生成树,稍稍总结一下,这是第一篇 kruskal算法 关于kruskal算法已有大量的资料,不再赘述,算法流程为: 得到邻接矩阵和权值: 初始化,连接距离最小的两点: 连接距离次小的两点, ...
- 51nod1743-雪之国度【最小生成树,LCA,并查集】
正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1743 题目大意 nnn个点mmm条边的一张图,每次询问要求找出x,yx, ...
- POJ - 3694 Network(边双缩点+LCA+并查集优化)
题目链接:点击查看 题目大意:给出一个由n个点组成的无向图,现在有m次操作,每次操作都会向图中增加一条无向边,每次操作后询问当前图中有多少个桥 题目分析:题意很好理解,思路也很好想,就是代码量有点小多 ...
- POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)
[题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...
- 【割边缩点】解题报告:POJ - 3694 - Network(Tarjan割边缩点 + LCA + 并查集优化)
POJ - 3694 - Network 给定一张N个点M条边的无向连通图,然后执行Q次操作,每次向图中添加一条边,并且询问当前无向图中"桥"的数量.N≤105,M≤2∗105,Q ...
- POJ 3694 (tarjan缩点+LCA+并查集)
好久没写过这么长的代码了,题解东哥讲了那么多,并查集优化还是很厉害的,赶快做做前几天碰到的相似的题. 1 #include <iostream> 2 #include <algori ...
- 最小生成树kruskal算法并查集版 C语言实现
今天数据结构课讲了最小生成树的Kruskal算法和Prim算法,不过都只是概念,可能是怕他们听不懂吧,反正算法实现一概不讲...囧 下午抱着<算法导论>跑去图书馆看Kruskal算法,发现 ...
- 最小生成树KrusKal算法(并查集)
洛谷p1111链接 克鲁斯卡尔算法的思路就是由森林变成树的过程,其中最主要的就是贪心和并查集的应用. 我们知道链接n个点需要n-1条边,这就满足的最后生成的是一颗树,而不是一个环.在这n-1条边的选择 ...
- 最小生成树Kruskal算法+并查集检查连通
/* 10 6 1 2 6 1 3 1 1 4 5 2 3 5 2 5 3 3 4 5 3 5 6 3 6 4 4 6 2 5 6 6 */// 本例解决最小生成树问题 // 并查集来加快效率 // ...
最新文章
- Ubuntu下安装中文输入法(本文安装的搜狗输入法)
- 微信小程序-学习笔记6-组件
- release 无法打开windows.h vs_Windows 10 Build 21270发布:Cortana新增打开/搜索文件技能...
- Approximate Nearest Neighbors.接近最近邻搜索
- 如何清除tomcat缓存
- C++——override
- 遇到代码缺陷不要慌,马上教你快速检测和修复
- 短文本合并重复(去重)的简单有效做法
- bagging和时间序列预测_Simple RNN时间序列预测
- HCIE-Security Day38:理论学习:信息安全管理
- 第三章 python流程控制
- VS2017 CUDA编程学习实例1:CUDA实现向量点乘
- 自动控制原理3.3---二阶系统的时域分析
- C# 在Word文档中生成条形码
- python3 get函数,python3请求的GET方法
- 【模糊综合评价的运用】——《电子舌技术在食用盐模糊感官评价中的应用》论文笔记(内附MATLAB程序)
- ubuntunbsp;16.04安装smba服务
- Solana 基金会与韩国区块链孵化器 ROK Capital 合作推出 2000 万美元生态基金
- (华师)CSMA技术的P—坚持算法规则是什么?
- 一曲清商 满墨柔情不知数