题意
动态维护最小生成树上最大边
题解
这题有点恶心,还要写一个hash
因为最小生成树具有环切性质,所以LCT维护一下就可以了
代码
#include
#include
#include
#include
#include
#include
#define L(i) (T[i].s[0])
#define R(i) (T[i].s[1])
#define F(i) (T[i].fa)
#define mx(i) (T[i].mx)
#define Loc(i) (R(F(i))==i)
#define W(i) (T[i].w)
#define For(i,j,k) for(int i=(j);i<=(int)k;i++)
#define Forr(i,j,k) for(int i=(j);i>=(int)k;i--)
#define Set(a,b) memset(a,b,sizeof(b))
#define Rep(i,u) for(int i=Begin[u],v=to[i];i;i=Next[i],v=to[i])
#define ll long long
using namespace std;
const int N=100010,INF=0x3f3f3f3f,M=1000010;
inline void read(int &x){
x=0;int f(0);char c=getchar();
while(c<'0'||c>'9')f|=(c=='-'),c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
if(f)x=-x;
}
struct edge{
int u,v,w,mk,id;
}E[M];
inline bool cmp1(edge a,edge b){
return a.winline bool cmp2(edge a,edge b){
return a.idstruct node{
int s[2],w,mx,fa,rev;
};
struct LCT{
node T[M+N];
inline void init(){Set(T,0);}
inline void pushup(int x){
mx(x)=x;
if(L(x)&&W(mx(L(x)))>W(mx(x)))mx(x)=mx(L(x));
if(R(x)&&W(mx(R(x)))>W(mx(x)))mx(x)=mx(R(x));
}
inline void pushdown(int x){
if(T[x].rev){
T[x].rev^=1,T[L(x)].rev^=1,T[R(x)].rev^=1;
swap(L(x),R(x));
}
}
inline bool isrt(int x){
return R(F(x))!=x&&L(F(x))!=x;
}
inline void Pushdown(int x){
if(!isrt(x))Pushdown(F(x));
pushdown(x);
}
inline void Rotate(int x){
int A=F(x),B=F(A),l=Loc(x),r=l^1,d=Loc(A);
if(!isrt(A))T[B].s[d]=x;F(x)=B;
F(A)=x,F(T[x].s[r])=A,T[A].s[l]=T[x].s[r],T[x].s[r]=A;
pushup(A);
}
inline void splay(int x){
Pushdown(x);
while(!isrt(x)){
if(!isrt(F(x)))Rotate(x);
Rotate(x);
}
pushup(x);
}
inline void access(int x){
for(int i=0;x;i=x,x=F(x))splay(x),R(x)=i,pushup(x);
}
inline void reverse(int x){
access(x);
splay(x);
T[x].rev^=1;
}
inline int findrt(int x){
access(x),splay(x);
while(L(x))x=L(x);
return x;
}
inline void link(int x,int y){
reverse(x),F(x)=y;
}
inline void cut(int x,int y){
reverse(x),access(y),splay(y);
L(y)=F(x)=0;pushup(y);
}
inline int query(int x,int y){
reverse(x),access(y),splay(y);
return mx(y);
}
inline void modify(int x,int y,int num,int n){
int e=query(x,y);
if(W(e)return;
cut(e,E[e-n].u);
cut(e,E[e-n].v);
link(x,num);
link(num,y);
}
}t;
struct ufs{
int f[N];
int Find(int x){return f[x]==x?x:f[x]=Find(f[x]);}
inline void init(int n){For(i,1,n)f[i]=i;}
inline bool Union(int x,int y){
int a=Find(x),b=Find(y);
if(a==b)return 0;
f[a]=b;
return 1;
}
}s;
inline void Kruskal(int n,int m){
int tot=0;
s.init(n);
sort(E+1,E+m+1,cmp1);
For(i,1,m)
if(tot1&&!E[i].mk&&s.Union(E[i].u,E[i].v))
t.link(E[i].u,E[i].id+n),t.link(E[i].id+n,E[i].v),++tot;
sort(E+1,E+m+1,cmp2);
}
edge oper[N];
int ans[N],n,m,q;
const int Mod=1000037;
struct Hash{
ll Begin[Mod+10],Next[Mod+10],to[Mod+10],w[Mod+10][2],e;
Hash(){
Set(Begin,0),e=0;
}
inline void add(ll key,ll val,ll x,ll y){
to[++e]=val,Next[e]=Begin[key],Begin[key]=e;w[e][0]=x,w[e][1]=y;
}
inline void insert(ll x,ll y,ll val){
if(x>y)swap(x,y);
ll key=(x-1)*n+y;
key%=Mod;
add(key,val,x,y);
}
inline ll find(ll x,ll y){
if(x>y)swap(x,y);
ll key=(x-1)*n+y;
key%=Mod;
Rep(i,key)
if(w[i][0]==x&&w[i][1]==y)
return v;
}
}H;
int main(){
read(n),read(m),read(q);
For(i,1,m)read(E[i].u),read(E[i].v),read(E[i].w),
H.insert(E[i].u,E[i].v,(E[i].id=i)),t.T[n+i].w=E[i].w,t.pushup(n+i);
For(i,1,q){
read(oper[i].mk),read(oper[i].u),read(oper[i].v);
if(oper[i].mk==2)oper[i].w=H.find(oper[i].u,oper[i].v);
if(oper[i].mk==2)E[oper[i].w].mk=1;
}
Kruskal(n,m);
Forr(i,q,1){
if(oper[i].mk==2)t.modify(oper[i].u,oper[i].v,oper[i].w+n,n);
else {
int k=t.query(oper[i].u,oper[i].v)-n;
ans[i]=E[k].w;
}
}
For(i,1,q)
if(oper[i].mk==1)
printf("%d\n",ans[i]);
return 0;
}