bzoj2594: [Wc2006]水管局长数据加强版
居然1A,思路清晰的好处。
题目不再解释;
题目要求维护两点间最小的路径所经过边的权值最大值,很显然,这东西肯定是在MST上;
Kruskal跑出MST,就可以在树上随便搞;
但题目有删边要求,删边不好做,干脆反过来做成加边;
用LCT维护一下两点间最大的边就好了;
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<cstdlib> #include<ctime> #include<algorithm> using namespace std; #define mid ((l+r)>>1) #define LL long long #define FILE "dealing" #define up(i,j,n) for(LL i=(j);i<=(n);i++) #define pii pair<int,int> int read(){ int x=0,f=1,ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=getchar(); return f*x; } const int maxn=300010,inf=100000000,mod=998244353; int n,m,q; struct edge{int x,y,v;}b[1001000]; bool cmp(edge a,edge b){return a.v<b.v;} struct node{int y,next,v;}e[2000000],k[2000000]; int len,linkk[2000000],cnt,Link[2000000],fa[maxn],x[maxn],y[maxn],ans[maxn],Max[maxn],cnt_point,w[maxn],f[maxn][2],val[maxn]; void insert(node* e,int* linkk,int& len,int x,int y,int v){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;e[len].v=v;} int ch[maxn],u[maxn],v[maxn]; namespace Kruskal{ int fa[maxn]; int getfa(int x){return x==fa[x]?x:fa[x]=getfa(fa[x]);} void kruskal(){ cnt_point=n; bool flag=0; up(i,1,n)fa[i]=i; up(i,1,m){ flag=0; for(int j=Link[b[i].x];j;j=k[j].next) if(k[j].y==b[i].y){ val[k[j].v]=b[i].v; flag=1; break; } for(int j=Link[b[i].y];j;j=k[j].next) if(k[j].y==b[i].x){ val[k[j].v]=b[i].v; flag=1; break; } if(flag)continue; getfa(b[i].x),getfa(b[i].y); if(fa[b[i].x]==fa[b[i].y])continue; fa[b[i].x]=fa[b[i].y]; cnt_point++; f[cnt_point][0]=b[i].x,f[cnt_point][1]=b[i].y; insert(e,linkk,len,b[i].x,cnt_point,b[i].v); insert(e,linkk,len,cnt_point,b[i].x,b[i].v); insert(e,linkk,len,b[i].y,cnt_point,b[i].v); insert(e,linkk,len,cnt_point,b[i].y,b[i].v); } } }; namespace DFS{ void dfs(int x){ for(int i=linkk[x];i;i=e[i].next){ if(e[i].y==fa[x])continue; if(x>n)w[x]=e[i].v; Max[x]=x; fa[e[i].y]=x; dfs(e[i].y); } } }; namespace LCT{ int c[maxn][2],rev[maxn],q[maxn],top; void reve(int o){rev[o]^=1,swap(c[o][0],c[o][1]);} void pushdown(int o){if(rev[o])reve(c[o][0]),reve(c[o][1]),rev[o]^=1;} void updata(int o){ Max[o]=o; if(w[Max[c[o][1]]]>w[Max[o]])Max[o]=Max[c[o][1]]; if(w[Max[c[o][0]]]>w[Max[o]])Max[o]=Max[c[o][0]]; } bool isroot(int o){return c[fa[o]][0]!=o&&c[fa[o]][1]!=o;} void rotate(int x){ int y=fa[x],z=fa[y],d=(c[y][1]==x); if(!isroot(y))c[z][c[z][1]==y]=x; fa[y]=x;fa[x]=z;fa[c[x][d^1]]=y; c[y][d]=c[x][d^1];c[x][d^1]=y; updata(y),updata(x); } void splay(int x){ q[++top]=x; for(int i=x;!isroot(i);i=fa[i])q[++top]=fa[i]; while(top)pushdown(q[top--]); while(!isroot(x)){ int y=fa[x],z=fa[y]; if(!isroot(y)){ if(c[y][1]==x^c[z][1]==y)rotate(x); else rotate(y); } rotate(x); } } void access(int x){ for(int t=0;x;t=x,x=fa[x]) splay(x),c[x][1]=t,updata(x); } void makeroot(int x){ access(x);splay(x);reve(x); } void cut(int x,int y){ makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0;updata(y); } void link(int x,int y){ makeroot(x);fa[x]=y; } }; int main(){ freopen(FILE".in","r",stdin); freopen(FILE".out","w",stdout); n=read(),m=read(),q=read(); up(i,1,m)b[i].x=read(),b[i].y=read(),b[i].v=read(); sort(b+1,b+m+1,cmp); up(i,1,q)ch[i]=read(),x[i]=read(),y[i]=read(); up(i,1,q)if(ch[i]==2){ insert(k,Link,cnt,x[i],y[i],i); insert(k,Link,cnt,y[i],x[i],i); } Kruskal::kruskal(); DFS::dfs(1); for(int i=q;i>0;i--){ if(ch[i]==1){ LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]); ans[i]=w[Max[y[i]]]; } if(ch[i]==2){ LCT::makeroot(x[i]),LCT::access(y[i]),LCT::splay(y[i]); int t=Max[y[i]]; if(val[i]<w[t]){ LCT::cut(f[t][0],t);LCT::cut(f[t][1],t); cnt_point++; f[cnt_point][0]=x[i],f[cnt_point][1]=y[i]; w[cnt_point]=val[i]; LCT::link(x[i],cnt_point); LCT::link(y[i],cnt_point); } } } up(i,1,q)if(ch[i]==1)printf("%d\n",ans[i]); return 0; }