codeforces 827D(kruskal+倍增+并查集)
来源:互联网 发布:java识别图片中文文字 编辑:程序博客网 时间:2024/06/06 09:25
传送门
题解:先求出最小生成树,用倍增LCA求出不在最小生成树中的边的答案,同时再用这个答案它去更新最小生成树中的边的答案。为了提高更新这一操作的效率,枚举有序(从小到大)的边集,更新过的用并查集连在一起(由于从小到大,小的最优,下条边一定不会再次更新它们),下一次直接往上跳即可。
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;const int MAXN=2e5+2,INF=0x3f3f3f3f;struct kruskal { int u,v,w,id; friend bool operator <(const kruskal &a,const kruskal &b) { return a.w<b.w; }}kr[MAXN];int head[MAXN],edge;struct EDGE { int v,nxt,w,id;}e[MAXN<<1];bool inm[MAXN];int n,m;int fa[MAXN];int ans[MAXN];int anc[MAXN][19],mx[MAXN][19],dep[MAXN],up[MAXN];inline int read() { int x=0;char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar(); return x;}inline void adde(int u,int v,int w,int id) { e[edge].nxt=head[u],e[edge].v=v,e[edge].id=id,e[edge].w=w,head[u]=edge++; e[edge].nxt=head[v],e[edge].v=u,e[edge].id=id,e[edge].w=w,head[v]=edge++;}int find(int x) { return fa[x]==x?x:fa[x]=find(fa[x]);}void dfs(int p,int f,int d) { dep[p]=dep[f]+1,anc[p][0]=f,mx[p][0]=d; for (int i=1;i<=18;++i) anc[p][i]=anc[anc[p][i-1]][i-1],mx[p][i]=max(mx[p][i-1],mx[anc[p][i-1]][i-1]); for (int i=head[p];~i;i=e[i].nxt) { int v=e[i].v; if (v==f) continue; up[v]=e[i].id,dfs(v,p,e[i].w); }}int lca(int x,int y,int &d) { d=0;if (dep[x]<dep[y]) x^=y^=x^=y; for (int i=18;i>=0;--i) { if (dep[anc[x][i]]>=dep[y]) { d=max(d,mx[x][i]); x=anc[x][i]; } } if (x==y) return x; for (int i=18;i>=0;--i) { if (anc[x][i]^anc[y][i]) { d=max(d,max(mx[x][i],mx[y][i])); x=anc[x][i],y=anc[y][i]; } } d=max(d,max(mx[x][0],mx[y][0])); return anc[x][0];}void modify(int x,int lca,int w) { x=find(x); while (dep[x]>dep[lca]) { ans[up[x]]=min(ans[up[x]],w); int y=find(anc[x][0]); fa[x]=y; x=find(x); }}int main() {// freopen("codeforces 827D.in","r",stdin); while (~scanf("%d%d",&n,&m)) { memset(head,-1,sizeof(head)); memset(inm,0,sizeof(inm)); edge=0; for (register int i=1;i<=n;++i) fa[i]=i; for (register int i=1;i<=m;++i) kr[i].id=i,kr[i].u=read(),kr[i].v=read(),kr[i].w=read(); sort(kr+1,kr+m+1); int blo=n; for (register int i=1;i<=m&&blo>1;++i) { int u=kr[i].u,v=kr[i].v; u=find(u),v=find(v); if (u^v) { fa[u]=v,inm[i]=true,--blo; adde(kr[i].u,kr[i].v,kr[i].w,kr[i].id); } } dfs(1,0,0); memset(ans,INF,sizeof(ans)); for (register int i=1;i<=n;++i) fa[i]=i; for (register int i=1;i<=m;++i) { if (inm[i]) continue; int u=kr[i].u,v=kr[i].v,f=lca(u,v,ans[kr[i].id]); --ans[kr[i].id]; modify(u,f,kr[i].w-1); modify(v,f,kr[i].w-1); } for (int i=1;i<=m;++i) printf("%d\n",ans[i]==INF?-1:ans[i]); } return 0;}
阅读全文
0 0
- codeforces 827D(kruskal+倍增+并查集)
- CodeForces 827D Best Edge Weight (倍增 启发式合并 链剖 并查集)
- Codeforces 827D Best Edge Weight (最小生成树 + 树链剖分/倍增/并查集)
- CodeForces 25D(并查集)
- kruskal+ 并查集
- Kruskal+并查集
- Kruskal + 并查集
- CodeForces 151D Quantity of Strings(并查集)
- Codeforces Round #334 D. Moodular Arithmetic(并查集)
- CodeForces 292D Connected Components (并查集+YY)
- CodeForces 566 D.Restructuring Company(并查集)
- CodeForces 566 D.Restructuring Company(并查集)
- Codeforces 366D 贪心+并查集
- Codeforces 371D. Vessels【并查集】
- codeforces 366D 并查集
- codeforces 593D(并查集 + LCA)
- codeforces 691D 并查集
- [Codeforces 325 D. Reclamation]并查集
- Android应用程序的Activity启动过程简要介绍和学习计划
- mysql_存储过程
- GC详解及Minor GC和Full GC触发条件总结
- Image Smoothing via L0 Gradient Minimization
- 比特币的原理及运作机制
- codeforces 827D(kruskal+倍增+并查集)
- mysql_触发器
- python从入门到实践:10-6 加法运算
- Linux功耗管理(23)_Linux PM QoS framework(2)_PM QoS class
- A_Byte_Of_Python_1
- 二、log4j配置文件说明
- List<T>排序工具类---泛型和反射实现
- normalize 函数使用
- 0-1背包