题解:
很显然的是要用到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 }