题目
A-B路径的最长边最小 这个路径一定在最小生成树上。可以离线做。删边不好做。看成倒序加边。先维护一个最小生成树。每次加边的时候 看这个边是否小于最小生成树中A-B路径的最长边(一定是这样!!! 然后保证新添加的边是有用边 不会成环的),小于的话,将那个边删了,添加这条边。怎么记录答案呢。把边当成一个带权值的点。 而
下面的代码只在洛谷过了 bzoj不能用map记录边的编号 先按x y(x优先)排序。然后在L[x],R[x]二分查找他的编号。我deubg了好久,还是没过。好伤心。不想写了。
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int N=1e5+5,M=1e6+5;
struct node{int x,y,w;}e[M],q[M];
inline int cmp(node A,node B){return A.w<B.w;}
int f[N+M],ch[N+M][2],tag[N+M],st[N+M];
int mx[N+M],val[N+M],F[N+M];
map<pair<int,int>,int>mp;
inline int seek(int x){return (x==F[x])?(x):(F[x]=seek(F[x]));}
inline void combine(int x,int y){x=seek(x),y=seek(y),F[x]=y;}
inline void pushup(int x){
mx[x]=val[x];
if(e[mx[ch[x][0]]].w>e[mx[x]].w) mx[x]=mx[ch[x][0]];
if(e[mx[ch[x][1]]].w>e[mx[x]].w) mx[x]=mx[ch[x][1]];
}
inline void pushdown(int x){
if(!tag[x]) return;
swap(ch[ch[x][0]][0],ch[ch[x][0]][1]),tag[ch[x][0]]^=1;
swap(ch[ch[x][1]][0],ch[ch[x][1]][1]),tag[ch[x][1]]^=1;
tag[x]=0;
}
inline int notroot(int x){
return ch[f[x]][0]==x||ch[f[x]][1]==x;
}
inline void route(int x){
int y=f[x],z=f[y],w=(ch[y][1]==x);
if(notroot(y)) ch[z][ch[z][1]==y]=x;
f[x]=z;
ch[y][w]=ch[x][w^1];if(ch[y][w]) f[ch[y][w]]=y;
ch[x][w^1]=y,f[y]=x;
pushup(y),pushup(x);
}
inline void splay(int x){
int y=x,num=0;st[++num]=y;
while(notroot(y)) st[++num]=(y=f[y]);
while(num) pushdown(st[num--]);
if(!notroot(x)) return;
for(int fa=f[x];notroot(x);route(x),fa=f[x])
if(notroot(fa)) ((ch[fa][1]==x)^(ch[f[fa]][1]==fa))?route(x):route(fa);
}
inline void access(int x){
for(int y=0;x;x=f[y=x])
splay(x),ch[x][1]=y,pushup(x);
}
inline void makeroot(int x){
access(x),splay(x);
swap(ch[x][0],ch[x][1]),tag[x]^=1;
}
inline int findroot(int x){
access(x),splay(x);
while(ch[x][0]) pushdown(x),x=ch[x][0];
splay(x);return x;
}
inline void split(int x,int y){
makeroot(x),access(y),splay(y);
}
inline void link(int x,int y){
makeroot(x),makeroot(y),f[x]=y;
}
inline void cut(int x,int y){
//makeroot(x),splay(y),f[y]=ch[x][1]=0,pushup(x);//错的 万一x y在一颗splay中
split(x,y),f[x]=ch[y][0]=0,pushup(y);
}
int vis[M],ans[N];
int main(){
int n,m,qq;scanf("%d%d%d",&n,&m,&qq);
for(int i=1;i<=m;++i) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
for(int i=1;i<=n+m;++i) F[i]=i;
sort(e+1,e+m+1,cmp);e[0].w=0;
for(int i=1;i<=m;++i){
if(e[i].x>e[i].y) swap(e[i].x,e[i].y);
mp[make_pair(e[i].x,e[i].y)]=i,mx[i+n]=val[i+n]=i;
}
for(int i=1,typ;i<=qq;++i){
scanf("%d%d%d",&typ,&q[i].x,&q[i].y);
if(q[i].x>q[i].y) swap(q[i].x,q[i].y);
if(typ==2) q[i].w=mp[make_pair(q[i].x,q[i].y)],vis[q[i].w]=1;
}
for(int i=1,x,y,num=0;i<=m;++i){
if(num==n-1) break;
if(vis[i]) continue;
x=e[i].x,y=e[i].y;
if(seek(x)==seek(y)) continue;
link(x,i+n),link(y,i+n),combine(x,i+n),combine(y,i+n);
++num;
}
for(int i=qq,x,y;i>=1;--i){
x=q[i].x,y=q[i].y;
if(!q[i].w) split(x,y),ans[i]=e[mx[y]].w;
else{
split(x,y);int id=mx[y],newid=q[i].w;
if(e[newid].w<e[id].w){//cut(,id+n) 注意不要写mx[y]+n mx[y]在cut时变化了!!!
cut(e[id].x,id+n),cut(e[id].y,id+n);//WA了一天...
link(x,newid+n),link(y,newid+n);
}
}
}
for(int i=1;i<=qq;++i)
if(!q[i].w) printf("%d\n",ans[i]);
}