要明确一个事实:并查集删边是不存在的,不可能写的
所以离线之后把询问反过来做,变成加边 (这也是个老套路了)
对于删掉的边,用map存下它原来的编号
加回去的时候,询问(x,y)路径上的最大边权,看能否替换掉它。
但是众所周知LCT似乎只能维护点权。
那么就把边看作点,向两个端点连边,自身的点权就是边权。
由于替换的时候要断掉最大边,所以要保存点权最大的点的编号,而不是直接保存最大值。
询问就直接找到点权最大的那个点的编号,返回它的值。
然后就是板子了。
Code:
#include
#include
#include
#include
#include
#define maxn 200005
using namespace std;
inline void read(int &a){
char c;while(!isdigit(c=getchar()));
for(a=c-'0';isdigit(c=getchar());a=a*10+c-'0');
}
inline void print(int a){
if(a>=10) print(a/10);
putchar(a%10+48);
}
int F[maxn];
int Find(int x){return x==F[x]?x:F[x]=Find(F[x]);}
namespace LCT{
int ch[maxn][2],fa[maxn],pos[maxn],v[maxn],nb[maxn][2],tot;
bool rev[maxn];
#define il inline
#define pa fa[x]
il bool isc(int x){return ch[pa][1]==x;}
il bool isr(int x){return ch[pa][0]!=x&&ch[pa][1]!=x;}
il void pd(int x){
if(rev[x]){
swap(ch[x][0],ch[x][1]),rev[x]=0;
rev[ch[x][0]]^=1,rev[ch[x][1]]^=1;
}
}
il void pdpath(int x){if(!isr(x)) pdpath(pa);pd(x);}
il void upd(int x){
pos[x]=x;
if(v[pos[ch[x][0]]]>v[pos[x]]) pos[x]=pos[ch[x][0]];
if(v[pos[ch[x][1]]]>v[pos[x]]) pos[x]=pos[ch[x][1]];
}
il void rot(int x){
int y=fa[x],z=fa[y],c=isc(x);
if(!isr(y)) ch[z][ch[z][1]==y]=x;
(ch[y][c]=ch[x][!c])&&(fa[ch[y][c]]=y);
fa[ch[x][!c]=y]=x,fa[x]=z;
upd(y),upd(x);
}
il void splay(int x){
pdpath(x);
for(;!isr(x);rot(x))
if(!isr(pa)) rot(isc(pa)==isc(x)?pa:x);
}
il int access(int x,int y=0){
for(;x;x=fa[y=x]) splay(x),ch[x][1]=y,upd(x);
return y;
}
il void bert(int x){
access(x),splay(x),rev[x]^=1;
}
il void link(int x,int y){
bert(x),fa[x]=y;
}
il void cut(int x,int y){
bert(x),access(y),splay(y);
fa[x]=ch[y][0]=0;
upd(y);
}
il int split(int x,int y){
bert(x),access(y),splay(y);
return y;
}
il void insert(int x,int y,int w){
if(Find(x)!=Find(y)){
v[++tot]=w,pos[tot]=tot;
nb[tot][0]=x,nb[tot][1]=y;
link(tot,x),link(y,tot);
F[Find(x)]=Find(y);
return;
}
int tmp=pos[split(x,y)];
if(w<v[tmp]){
cut(tmp,nb[tmp][0]),cut(tmp,nb[tmp][1]);
v[tmp]=w,pos[tmp]=tmp,nb[tmp][0]=x,nb[tmp][1]=y;
link(tmp,x),link(y,tmp);
}
}
il int qmax(int x,int y){return v[pos[split(x,y)]];}
}
struct node{
int x,y,z,tim;
bool operator < (const node &p)const{return tim==p.tim?z<p.z:tim>p.tim;}
}e[maxn*5],q[maxn>>1];
map<int,int>id[maxn>>1];
int n,m,Q,cnt,idx,op,x,y,ans[maxn>>1];
char c;
int main()
{
read(n),read(m),read(Q);
for(int i=1;i<=m;i++){
read(e[i].x),read(e[i].y),read(e[i].z);
if(e[i].x>e[i].y) swap(e[i].x,e[i].y);
id[e[i].x][e[i].y]=i;
}
for(int i=1;i<=Q;i++){
read(op),read(x),read(y);if(x>y) swap(x,y);
if(op==1) q[++cnt].x=x,q[cnt].y=y,q[cnt].tim=idx;
else e[id[x][y]].tim=++idx;
}
for(int i=1;i<=m;i++) if(!e[i].tim) e[i].tim=idx+1;
sort(e+1,e+1+m);
int j=1;for(int i=1;i<=n;i++) F[i]=i;
LCT::tot=n;//!!
for(;e[j].tim==idx+1;j++) if(Find(e[j].x)!=Find(e[j].y)) LCT::insert(e[j].x,e[j].y,e[j].z);
for(int i=cnt;i>=1;i--){
for(;j<=m&&e[j].tim>q[i].tim;j++)
LCT::insert(e[j].x,e[j].y,e[j].z);
ans[i]=LCT::qmax(q[i].x,q[i].y);
}
for(int i=1;i<=cnt;i++) print(ans[i]),putchar('\n');
}