您的位置:首页 > 其它

NKOJ 2698 Nicole的博客 (动态树+最小生成树)

2017-12-01 20:17 302 查看

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 2000005
using namespace std;
struct node{int x,y,z,id;bool f;}edge
;
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
,F
,Hash
;
int ty
,A
,B
,Ans
;
int ls
,rs
,fa
,Max
,id
,v
,rev
;
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<
101b9
/span>(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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: