[WC 2006] 水管局长数据加强版

题解:
很显然的是要用到kruskal算法,这样就能保证路径上的最大边权最小.
我们可以采取离线的方法,将删边化为加边就好了.先用没有删过的边跑kruskal,这样剩下的边就可以丢掉了.然后从后往前做.
对于操作一:直接询问即可,题目已经保证了两点相连了(想想为什么).
对于操作二:我们对需要加的边(u,v)进行讨论.如果u和v没有连通,直接link操作.如果u和v已经连通了,但路径上的最大边权大于这条边的边权,那么我们先cut,在link.
对于读取边信息的LCT,我们用的方法是对于一条边(u,v),建一个需点x,将边的信息存在x上,然后连接u和x以及v和x就可以了.

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<queue>
  8 #include<vector>
  9 #include<stack>
 10 #include<map>
 11 #define MAXN 2000010
 12 #define RG register
 13 #define LL long long int
 14 using namespace std;
 15 const int INF=1e9;
 16 const int mod=31011;
 17 typedef pair<int,int> pi;
 18 struct node{
 19   int x,y,z;int id;
 20 }t[MAXN];
 21 struct ed{
 22   int l,r,w;int vi;
 23 }e[MAXN];
 24 int n,m,Q;
 25 int ch[MAXN][2],mal[MAXN],fa[MAXN],rev[MAXN];
 26 int val[MAXN];
 27 int ans[MAXN];
 28 int q[MAXN],top;
 29 map<pi,int> p;
 30 int gi()
 31 {
 32   int x=0,f=1;char ch=getchar();
 33   while(ch<'0' || ch>'9'){ if(ch=='-') f*=-1;ch=getchar();}
 34   while(ch>='0'&&ch<='9'){ x=x*10+ch-'0';ch=getchar();}
 35   return x*f;
 36 }
 37 bool cmp(ed a,ed b){ return a.w<b.w;}
 38 bool isroot(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
 39 void up(int x){
 40   int l=ch[x][0],r=ch[x][1];
 41   mal[x]=x;
 42   if(val[mal[l]]>val[mal[x]]) mal[x]=mal[l];
 43   if(val[mal[r]]>val[mal[x]]) mal[x]=mal[r];
 44 }
 45 void down(int x){
 46   if(rev[x])
 47     {
 48       swap(ch[x][0],ch[x][1]);
 49       rev[x]^=1;rev[ch[x][0]]^=1;rev[ch[x][1]]^=1;
 50     }
 51 }
 52 void rotate(int x)
 53 {
 54   int old=fa[x],oldf=fa[old],rel=(ch[old][1]==x);
 55   if(!isroot(old))
 56     ch[oldf][ch[oldf][1]==old]=x;
 57   fa[x]=oldf;fa[ch[x][rel^1]]=old;ch[old][rel]=ch[x][rel^1];
 58   fa[old]=x;ch[x][rel^1]=old;
 59   up(old);up(x);
 60 }
 61 void splay(int x)
 62 {
 63   int old,oldf,now=x;top=0;q[++top]=now;
 64   while(!isroot(now)) q[++top]=fa[now],now=fa[now];
 65   while(top){ down(q[top]);top--;}
 66   while(!isroot(x))
 67     {
 68       old=fa[x];oldf=fa[old];
 69       if(!isroot(old))
 70     {
 71       if((ch[old][0]==x)||(ch[oldf][0]==old)) rotate(x);
 72       else rotate(old);
 73     }
 74       rotate(x);
 75     }
 76 }
 77 void access(int x){for(int t=0;x;t=x,x=fa[x]) splay(x),ch[x][1]=t,up(x);}
 78 void makeroot(int x){access(x);splay(x);rev[x]^=1;}
 79 int find(int x){access(x);splay(x);while(ch[x][0]) x=ch[x][0];return x;}
 80 void cut(int x,int y){makeroot(x);access(y);splay(y);if(ch[y][0]==x) ch[y][0]=fa[x]=0;}
 81 void link(int x,int y){makeroot(x);fa[x]=y;}
 82 int query(int x,int y){makeroot(x);access(y);splay(y); return mal[y];}
 83 int main()
 84 {
 85   //freopen("1.in","r",stdin);
 86   n=gi();m=gi();Q=gi();
 87   for(int i=1;i<=m;i++){
 88     e[i].l=gi();e[i].r=gi();e[i].w=gi();
 89    }  
 90   sort(e+1,e+m+1,cmp);
 91   for(int i=1;i<=m;i++){
 92     p[pi(e[i].l,e[i].r)]=i;p[pi(e[i].r,e[i].l)]=i;
 93     val[i+n]=e[i].w;mal[i+n]=i+n;
 94   }
 95   for(int i=1;i<=Q;i++)
 96     {
 97       t[i].z=gi();t[i].x=gi();t[i].y=gi();
 98       if(t[i].z==2){t[i].id=p[pi(t[i].x,t[i].y)];e[t[i].id].vi=1;}
 99     }
100   for(int i=1;i<=m;i++)
101     {
102       if(e[i].vi==1) continue;
103       if(find(e[i].l)!=find(e[i].r)){link(e[i].l,i+n),link(e[i].r,i+n);}
104     }
105   for(int i=Q;i>=1;i--)
106     {
107       if(t[i].z==1) ans[i]=val[query(t[i].x,t[i].y)];
108       else {
109     if(find(t[i].x)!=find(t[i].y)){ link(t[i].x,t[i].id+n);link(t[i].y,t[i].id+n);}
110     else{
111       int w=query(t[i].x,t[i].y);
112       if(e[t[i].id].w<val[w]){
113         cut(e[w-n].l,w);cut(e[w-n].r,w);link(t[i].x,t[i].id+n);link(t[i].y,t[i].id+n);
114       }
115     }
116       }
117     }
118   for(int i=1;i<=Q;i++)
119     if(t[i].z==1) printf("%d
",ans[i]);
120   return 0;
121 }
原文地址:https://www.cnblogs.com/Landlord-greatly/p/8098022.html