1. 程式人生 > >[WC2006]水管局長——Link Cut Tree加邊維護MST

[WC2006]水管局長——Link Cut Tree加邊維護MST

題目大意:

給定一個圖,有兩種操作,一種詢問從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; }