NKOJ 2698 Nicole的博客 (动态树+最小生成树)
来源:互联网 发布:浏览器缺少java插件 编辑:程序博客网 时间:2024/06/11 02:34
P2698【动态树】Nicole的博客
问题描述
给你一个由N个节点M条带权边构成的无向简单图,然后进行Q次操作:
·1 x y :询问一条连接x,y的路径,使路径上权值最大的边权值最小;
·2 x y :删除原本连接x,y的边,保证这条边存在。
对每次询问,输出路径上权值最大的边的权值。
输入格式
第一行三个数N,M,Q
接下来M行每行三个数x,y,z,表示有一条连接x,y的边,权值为z
接下来Q行,每行k,x,y,表示一次操作
输出格式
对每次询问输出一行
样例输入
4 4 3
1 2 2
2 3 3
3 4 2
1 4 2
1 1 4
2 1 4
1 1 4
样例输出
2
3
提示
1<=N<=100000
1<=M<=1000000
1<=Q<=100000
1<=x,y<=N
1<=z<=109
保证任意时刻整个图连通
由询问可知,显然维护一颗最小生成树,然后考虑操作二,删边,不好操作。
考虑离线,显然倒序讨论,那么删边变成加边,用LCT维护这颗最小生成树,直接搞就好。
关于处理边权,将边变成点,然后往两个端点连边即可转化成点权。
代码:
#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>#define N 2000005using namespace std;struct node{int x,y,z,id;bool f;}edge[N];bool cmp1(node a,node b){return a.z<b.z;}bool cmp2(node a,node b){ if(a.x==b.x)return a.y<b.y; return a.x<b.x;}int n,m,q,top,S[N],F[N],Hash[N];int ty[N],A[N],B[N],Ans[N];int ls[N],rs[N],fa[N],Max[N],id[N],v[N],rev[N];int GM(int x,int y,int z){ if(x>=y&&x>=z)return x; if(y>=z)return y; return z;}bool Isroot(int x){return ls[fa[x]]!=x&&rs[fa[x]]!=x;}void MT(int p){ Max[p]=GM(v[p],Max[ls[p]],Max[rs[p]]); if(Max[p]==v[p])id[p]=p; else if(Max[p]==Max[ls[p]])id[p]=id[ls[p]]; else id[p]=id[rs[p]];}void PD(int p){ if(rev[p]) { swap(ls[p],rs[p]); rev[ls[p]]^=1; rev[rs[p]]^=1; rev[p]^=1; }}void Zig(int x){ int y=fa[x],z=fa[y]; if(!Isroot(y))y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z; ls[y]=rs[x];fa[rs[x]]=y; rs[x]=y;fa[y]=x; MT(y);MT(x);}void Zag(int x){ int y=fa[x],z=fa[y]; if(!Isroot(y))y==ls[z]?ls[z]=x:rs[z]=x;fa[x]=z; rs[y]=ls[x];fa[ls[x]]=y; ls[x]=y;fa[y]=x; MT(y);MT(x);}void Splay(int x){ int i,y,z; S[++top]=x; for(i=x;!Isroot(i);i=fa[i])S[++top]=fa[i]; while(top)PD(S[top--]); while(!Isroot(x)) { y=fa[x];z=fa[y]; if(!Isroot(y)) { if(y==ls[z])x==ls[y]?(Zig(y),Zig(x)):(Zag(x),Zig(x)); else x==rs[y]?(Zag(y),Zag(x)):(Zig(x),Zag(x)); } else x==ls[y]?Zig(x):Zag(x); }}void Access(int x){ for(int t=0;x;x=fa[x]) { Splay(x); rs[x]=t; MT(x);t=x; }}void Makeroot(int x){ Access(x); Splay(x); rev[x]^=1;}void Link(int x,int y){ Makeroot(x); fa[x]=y;}void Cut(int x,int y){ Makeroot(x); Access(y); Splay(y); ls[y]=fa[x]=0;}int GF(int x){ if(F[x]!=x)F[x]=GF(F[x]); return F[x];}void Kruscal(){ int i=1,cnt=0,x,y,fx,fy; while(cnt<n-1) { if(edge[i].f){i++;continue;} x=GF(edge[i].x); y=GF(edge[i].y); if(x!=y) { F[x]=y; cnt++; Link(edge[i].id,edge[i].x); Link(edge[i].id,edge[i].y); } i++; }}int main(){ int i,j,k,x,y,z;node tmp; scanf("%d%d%d",&n,&m,&q); for(i=1;i<=m;i++) { scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].z); if(edge[i].y<edge[i].x)swap(edge[i].x,edge[i].y); edge[i].id=n+i;v[n+i]=edge[i].z; } sort(edge+1,edge+m+1,cmp2); for(i=1;i<=q;i++) { scanf("%d%d%d",&ty[i],&A[i],&B[i]); if(ty[i]==1)continue; if(A[i]>B[i])swap(A[i],B[i]); tmp.x=A[i];tmp.y=B[i]; j=lower_bound(edge+1,edge+m+1,tmp,cmp2)-edge; edge[j].f=1; } for(i=1;i<=m;i++)Hash[edge[i].id]=i; for(i=1;i<=n;i++)F[i]=i; sort(edge+1,edge+m+1,cmp1); Kruscal(); sort(edge+1,edge+m+1,cmp2); for(i=q;i>=1;i--) { if(ty[i]==1) { Makeroot(A[i]); Access(B[i]); Splay(B[i]); Ans[i]=Max[B[i]]; } else { tmp.x=A[i];tmp.y=B[i]; j=lower_bound(edge+1,edge+m+1,tmp,cmp2)-edge; Makeroot(A[i]); Access(B[i]); Splay(B[i]); if(edge[j].z<Max[B[i]]) { k=Hash[id[B[i]]]; Cut(edge[k].x,edge[k].id); Cut(edge[k].y,edge[k].id); Link(edge[j].x,edge[j].id); Link(edge[j].y,edge[j].id); } } } for(i=1;i<=q;i++)if(ty[i]==1)printf("%d\n",Ans[i]);}
阅读全文
0 0
- NKOJ 2698 Nicole的博客 (动态树+最小生成树)
- NKOJ 2991 (NOI 2014) 魔法森林 (动态树+最小生成树)
- NKOJ 2770 难度系数(最小生成树)
- nkoj 3468 最小差值生成树 水题解
- NKOJ 3611(CQOI 2016) 不同的最小割(分治+最小割=最小割树)
- NKOJ 2439 四叶草魔杖(最小生成树+状压dp/网络流)
- NKOJ 2784 (APIO 2013) 道路费用(最小生成树+缩点)
- 动态最小生成树
- nkoj 1313(noip2007)树网的核 与 nkoj 2650(SDOI2011)消防
- 完全动态最小生成树(sgu529,HNOI2010city)
- MST - 最小生成树 (转 “笑着走完自己的路” 的博客) 写的不错
- 连接的管道(最小生成树)
- 图的最小生成树
- 最小生成树的总结
- kruskal的最小生成树
- 最小生成树的算法
- 图的最小生成树
- 图的最小生成树
- 等额本金
- Unity3D
- 利用nginx配置负载均衡
- maven更改镜像路径为阿里镜像
- Easyui dataGrid 动态insertRow 包含datebox、validatebox组件,样式失效问题
- NKOJ 2698 Nicole的博客 (动态树+最小生成树)
- redis基础
- %00截断问题
- 输入多个半径,求面积、周长
- [ 莫队 树状数组 ] [ AHOI2013 ] BZOJ3236
- 【排序】冒泡排序
- [Leetcode] 487. Max Consecutive Ones II 解题报告
- Ubuntu17.04安装QQ和微信
- try...catch...finally和throws