Codeforces 827D (Round #423 Div. 1) D. Best Edge Weight 树上倍增
来源:互联网 发布:贴吧发帖软件 编辑:程序博客网 时间:2024/06/05 06:31
给了一个图,问你当每条边的长度最大为多少的时候可以成为最小生成树中的一条边。
先求最小生成树。
求完之后,分两种情况讨论:
1.若一条边不在生成树上,这条边肯定与生成树上的边共同构成了一个环。
若这条边替代环上的一条边,则权值最大必须小于环上的边的最大权值。
2.若一条边在生成树上,则还是看刚才每个不在生成树上的边和生成树构成的那个环:
对于每个不在生成树上的边,假设从u到v,那么它能替代的边就为生成树上u到v路径上的所有边。
这时,u到v的生成树路径上的所有边,权值必须小于这条边,否则就要被替代。
最大和最小权值,都可以利用倍增算法在树上更新。
#include <cstdio>#include <iostream>#include <string.h>#include <string> #include <map>#include <queue>#include <vector>#include <set>#include <algorithm>#include <math.h>#include <cmath>#include <stack>#define mem0(a) memset(a,0,sizeof(a))#define meminf(a) memset(a,0x3f,sizeof(a))using namespace std;typedef long long ll;typedef long double ld;const int maxn=200005,inf=0x3f3f3f3f; const ll llinf=0x3f3f3f3f3f3f3f3f; const ld pi=acos(-1.0L); int f[maxn],mxlen[maxn][20],mnlen[maxn][20],dep[maxn],fa[maxn][20],ans[maxn];bool use[maxn],visit[maxn];int num;vector<int> v[maxn];vector<int> d[maxn];struct Edge {int from,to,dist,id;};Edge edge[maxn*2];bool cmp(Edge a,Edge b) {return a.dist<b.dist; } int find(int x) {if (f[x]==x) return x; else {f[x]=find(f[x]);return f[x];}}void kruskal(int n,int m) {int cnt=0,i;for (i=1;i<=n;i++) f[i]=i;mem0(use);for (i=1;i<=m;i++) {int from=edge[i].from,to=edge[i].to;int fa=find(from),fb=find(to);if (fa!=fb) {cnt++;use[i]=1;v[from].push_back(to);v[to].push_back(from);d[from].push_back(edge[i].dist);d[to].push_back(edge[i].dist);if (cnt==n-1) return;f[fa]=fb;}}}void dfs(int now,int step) {visit[now]=1;dep[now]=step;for (int i=0;i<v[now].size();i++) {int to=v[now][i];if (!visit[to]) {fa[to][0]=now;mxlen[to][0]=d[now][i];dfs(to,step+1);}}}int getmaxlen(int x,int y) {if (dep[x]<dep[y]) swap(x,y);int i,ans=-inf;for (i=18;i>=0;i--) {if (dep[fa[x][i]]>=dep[y]) {ans=max(ans,mxlen[x][i]);x=fa[x][i]; }}if (x==y) return ans;for (i=18;i>=0;i--) {if (fa[x][i]!=fa[y][i]) {ans=max(ans,max(mxlen[x][i],mxlen[y][i]));x=fa[x][i];y=fa[y][i];}}ans=max(ans,max(mxlen[x][0],mxlen[y][0]));return ans;}void update(int x,int y,int val) {if (dep[x]<dep[y]) swap(x,y);int i;for (i=18;i>=0;i--) {if (dep[fa[x][i]]>=dep[y]) {mnlen[x][i]=min(val,mnlen[x][i]);x=fa[x][i]; }}if (x==y) return;for (i=18;i>=0;i--) {if (fa[x][i]!=fa[y][i]) {mnlen[x][i]=min(mnlen[x][i],val);mnlen[y][i]=min(mnlen[y][i],val);x=fa[x][i];y=fa[y][i];}}mnlen[x][0]=min(mnlen[x][0],val);mnlen[y][0]=min(mnlen[y][0],val);}int main() {num=0;int n,m,i,j,x,y,d;scanf("%d%d",&n,&m);for (i=1;i<=m;i++) {scanf("%d%d%d",&edge[i].from,&edge[i].to,&edge[i].dist);edge[i].id=i;}sort(edge+1,edge+m+1,cmp);kruskal(n,m);mem0(visit);fa[1][0]=0;dep[0]=-1;dfs(1,0); //binary liftsfor (j=1;j<=18;j++) {for (i=1;i<=n;i++) {fa[i][j]=fa[fa[i][j-1]][j-1];mxlen[i][j]=max(mxlen[i][j-1],mxlen[fa[i][j-1]][j-1]);}}meminf(ans);meminf(mnlen);for (i=1;i<=m;i++) {if (!use[i]) {ans[edge[i].id]=getmaxlen(edge[i].from,edge[i].to)-1;update(edge[i].from,edge[i].to,edge[i].dist-1);}}for (j=17;j>=0;j--) {for (i=1;i<=n;i++) {mnlen[i][j]=min(mnlen[i][j],mnlen[i][j+1]);mnlen[fa[i][j]][j]=min(mnlen[fa[i][j]][j],mnlen[i][j+1]);}}for (i=1;i<=m;i++) {if (use[i]) if (fa[edge[i].from][0]==edge[i].to) ans[edge[i].id]=mnlen[edge[i].from][0]; else ans[edge[i].id]=mnlen[edge[i].to][0];}for (i=1;i<=m;i++) {if (ans[i]==inf) printf("-1 "); else printf("%d ",ans[i]);}return 0;}
阅读全文
0 0
- Codeforces 827D (Round #423 Div. 1) D. Best Edge Weight 树上倍增
- CodeForces 827D Best Edge Weight (倍增 启发式合并 链剖 并查集)
- Codeforces 827D Best Edge Weight (最小生成树 + 树链剖分/倍增/并查集)
- Codeforces Round #423 (Div. 1, rated, based on VK Cup Finals) D. Best Edge Weight(最小生成树+LCA+树链剖分)
- Codeforces Round #423 Div. 2 F. Best Edge Weight (倍增法lca)(最小生成树mst)
- Codeforces Round #238 (Div. 1) D题(倍增lca)
- Codeforces Round #371 (Div. 1) D. Animals and Puzzle 二维倍增 ★ ★ ★
- Codeforces Round #294 (Div. 2) E 树上倍增lca
- Codeforces Round #202 (Div. 1) D. Turtles
- Codeforces Round #253 (Div. 1)D题
- Codeforces Round #225 (Div. 1) D. Antimatter
- Codeforces Round #276 (Div. 1) D. Kindergarten
- Codeforces Round #286 (Div. 1) C、D
- Codeforces Round #434 Div.1 D graph
- Codeforces Round #237 (Div. 2) D. Minesweeper 1D
- Codeforces Round #237 (Div. 2) D Minesweeper 1D
- Codeforces Round #237 (Div. 2)-D. Minesweeper 1D
- Codeforces Round #237 (Div. 2) D. Minesweeper 1D
- 找出动词前面的并以动词命名
- 【Python版】OpenCV学习笔记(1):安装
- signal-利用中断信号来干别的事情
- 同源策略及跨域
- 常用数据库对象
- Codeforces 827D (Round #423 Div. 1) D. Best Edge Weight 树上倍增
- C++中的编译预处理命令
- .NET实现多图拼接(拼图)
- Git多账号配置
- 一只简单的多线程爬虫,爬取京东网站
- hashmap遍历方法
- jquery 正则表达式之判断是否数字
- 深入理解OSGI的模块化
- HDU