题目大意:
给定一个图,有两种操作,一种询问从x到y的路径中经过的边的最大值得最小值,第二种操作删除一条边。
思路:
离线操作,反着来做,每次加边询问环上面最大的边是否大于新加的边,若是删掉此边加入新边。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
void File(){
freopen("[HNOI2010]CITY.in","r",stdin);
freopen("[HNOI2010]CITY.out","w",stdout);
}
#define REP(i,a,b) for(register int i=a;i<=b;++i)
#define DREP(i,a,b) for(register int i=a;i>=b;--i)
#define MREP(i,x) for(register int i=beg[x];i;i=E[i].last)
#define ll long long
#define inf (0x3f3f3f3f)
int _max(int _,int __){return _>__ ? _ : __;}
int _min(int _,int __){return _<__ ? _ : __;}
const int maxn=1e3+10;
const int maxm=1e5+10;
struct edge{
int u,v,w;
bool operator < (const edge &tt) const {
return w<tt.w;
}
}E[maxm];
int n,m,q,cnt;
struct lct{
#define lc ch[rt][0]
#define rc ch[rt][1]
#define rel(x) (ch[fa[x]][1]==x)
int va[maxn+maxm],Maxva[maxn+maxm],Maxnum[maxn+maxm],fa[maxn+maxm],ch[maxn+maxm][2],q[maxn+maxm],top;
bool tag[maxn+maxm];
bool isrt(int rt){return ch[fa[rt]][0]!=rt && ch[fa[rt]][1]!=rt;}
void pushdown(int rt){if(tag[rt])tag[rt]^=1,tag[lc]^=1,tag[rc]^=1,swap(lc,rc);}
void pushup(int rt){
Maxva[rt]=_max(va[rt],_max(Maxva[lc],Maxva[rc]));
if(Maxva[rt]==va[rt])Maxnum[rt]=rt;
else if(Maxva[rt]==Maxva[lc])Maxnum[rt]=Maxnum[lc];
else Maxnum[rt]=Maxnum[rc];
}
void rotate(int rt){
int f=fa[rt],r=rel(rt);
fa[rt]=fa[f];if(!isrt(f))ch[fa[f]][rel(f)]=rt;
fa[ch[rt][r^1]]=f;ch[f][r]=ch[rt][r^1];
fa[f]=rt;ch[rt][r^1]=f;
pushup(f);pushup(rt);
}
void splay(int rt){
top=1;q[top]=rt;
int u=rt;
while(!isrt(u))u=fa[u],q[++top]=u;
DREP(i,top,1)pushdown(q[i]);
while(!isrt(rt)){
int f=fa[rt];
if(!isrt(f))rotate(rel(f)==rel(rt) ? f : rt);
rotate(rt);
}
}
void access(int rt){for(int las=0;rt;las=rt,rt=fa[rt])splay(rt),rc=las,pushup(rt);}
void makert(int rt){access(rt);splay(rt);tag[rt]^=1;}
int findrt(int rt){access(rt);splay(rt);while(lc)rt=lc;return rt;}
bool con(int x,int y){makert(x);return (findrt(y)==x);}
void split(int x,int y){makert(x);access(y);splay(y);}
void link(int x,int y){if(con(x,y))return;makert(x);fa[x]=y;}
void cut(int x,int y){if(!con(x,y))return;split(x,y);if(ch[y][0]==x)ch[y][0]=0,fa[x]=0,pushup(y);}
int query_num(int x,int y){split(x,y);return Maxnum[y];}
int query(int x,int y){split(x,y);return Maxva[y];}
}T;
int ans[maxm],e[maxn][maxn];
struct node{
int key;
int x,y;
}Query[maxm];
bool vis[maxn][maxn];
int main(){
File();
scanf("%d%d%d",&n,&m,&q);
REP(i,1,m){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
++cnt;
E[cnt].u=u;E[cnt].v=v;
E[cnt].w=w;
e[u][v]=e[v][u]=cnt;
}
REP(i,1,n)T.Maxnum[i]=i;
REP(i,1,m)T.va[i+n]=T.Maxva[i+n]=E[i].w,T.Maxnum[i+n]=i+n;
REP(i,1,q){
scanf("%d%d%d",&Query[i].key,&Query[i].x,&Query[i].y);
if(Query[i].key==2){
vis[Query[i].x][Query[i].y]=1;
vis[Query[i].y][Query[i].x]=1;
}
}
REP(i,1,m){
int u=E[i].u,v=E[i].v,w=E[i].w;
if(vis[u][v])continue;
if(!T.con(u,v))T.link(i+n,u),T.link(i+n,v);
else{
int num=T.query_num(u,v);
if(T.va[num]<=w)continue;
T.cut(num,E[num-n].u);
T.cut(num,E[num-n].v);
T.link(i+n,u);
T.link(i+n,v);
}
}
int cnt1=0;
DREP(i,q,1){
int u=Query[i].x,v=Query[i].y,w=E[e[u][v]].w;
if(Query[i].key==1)ans[++cnt1]=T.query(u,v);
else{
int num=T.query_num(u,v);
if(T.va[num]<=w)continue;
T.cut(num,E[num-n].u);
T.cut(num,E[num-n].v);
T.link(e[u][v]+n,u);
T.link(e[u][v]+n,v);
}
}
DREP(i,cnt1,1)printf("%d\n",ans[i]);
return 0;
}