标签:bzoj bzoj2594 link-cut-tree kruskal
题目大意:给定一个无向图,多次删除某条边,多次查询两点之间路径上边权最大值的最小值
Link-Cut-Tree维护动态最小生成树
首先倒着做 将所有被删除的边标记(找边我用的排序+二分) 将没标记的边跑一遍Kruskal 求出最小生成树 然后每次加边和查询正常维护即可
LInk-Cut-Tree一气呵成写完,Kruskal尼玛写挂了…… 居然忘记把并查集连边 这我也是醉了
顺便吐槽一下题干上给的读入优化真尼玛弱……自己随便写一个都可以优化到RANK前十……
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct edge{ int x,y,z; bool operator < (const edge &Y) const { if(x==Y.x) return y<Y.y; return x<Y.x; } bool operator < (const pair<int,int> &Y) const { if(x==Y.first) return y<Y.second; return x<Y.first; } }edges[1001001]; struct abcd{ abcd *ls,*rs,*fa; int e,max_e; bool rev_mark; abcd (int x); void Push_Up(); void Push_Down(); void Reverse(); }*null=new abcd(0),*tree[1100100]; struct query{ int p,x,y; }queries[100100]; struct _edge{ int x,y,z,pos; bool operator < (const _edge &Y) const { return z < Y.z; } void operator = (const edge &Y) { x=Y.x; y=Y.y; z=Y.z; pos=(&Y)-edges; } }_edges[1001001]; struct Complex{ int to,z,next; }table[200200]; int head[100100],tot; int n,m,q; bool v[1001001]; int fa[100100]; int stack[100100],top; void Add(int x,int y,int z) { table[++tot].to=y; table[tot].z=z; table[tot].next=head[x]; head[x]=tot; } int Find(int x) { if(!fa[x]||fa[x]==x) return fa[x]=x; return fa[x]=Find(fa[x]); } inline bool Compare(int x,int y) { return edges[x].z < edges[y].z; } abcd :: abcd(int x) { ls=rs=fa=null; e=max_e=x; rev_mark=0; } void abcd :: Push_Up() { max_e=max(ls->max_e,rs->max_e,Compare); max_e=max(max_e,e,Compare); } void abcd :: Push_Down() { if(fa->ls==this||fa->rs==this) fa->Push_Down(); if(rev_mark) { ls->Reverse(); rs->Reverse(); rev_mark=0; } } void abcd :: Reverse() { swap(ls,rs); rev_mark^=1; } void Zig(abcd *x) { abcd *y=x->fa; y->ls=x->rs; x->rs->fa=y; x->rs=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); } void Zag(abcd *x) { abcd *y=x->fa; y->rs=x->ls; x->ls->fa=y; x->ls=y; x->fa=y->fa; if(y==y->fa->ls) y->fa->ls=x; else if(y==y->fa->rs) y->fa->rs=x; y->fa=x; y->Push_Up(); } void Splay(abcd *x) { x->Push_Down(); while(x->fa->ls==x||x->fa->rs==x) { abcd *y=x->fa,*z=y->fa; if(x==y->ls) { if(y==z->ls) Zig(y); Zig(x); } else { if(y==z->rs) Zag(y); Zag(x); } } x->Push_Up(); } inline void Access(abcd *x) { abcd *y=null; while(x!=null) { Splay(x); x->rs=y; x->Push_Up(); y=x;x=x->fa; } } inline void Move_To_Root(abcd *x) { Access(x); Splay(x); x->Reverse(); } inline abcd* Find_Root(abcd *x) { while(x->fa!=null) x=x->fa; return x; } inline void Link(abcd *x,abcd *y) { Move_To_Root(x); x->fa=y; } inline void Cut(abcd *x,abcd *y) { Move_To_Root(x); Access(y); Splay(y); y->ls=null; x->fa=null; y->Push_Up(); } inline char Get_Char() { static const int len=1<<15; static char buffer[len]; static char *S,*T; if(S==T) { T=(S=buffer)+fread(buffer,1,len,stdin); if(S==T)return EOF; } return *S++; } inline int Get_Int() { char c=Get_Char(); while(c<'0'||c>'9') c=Get_Char(); int re=0; while(c>='0'&&c<='9') re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char(); return re; } void Kruskal() { int i,top=0; for(i=1;i<=m;i++) if(!v[i]) _edges[++top]=edges[i]; sort(_edges+1,_edges+top+1); for(i=1;i<=top;i++) { int x=_edges[i].x,y=_edges[i].y; if( Find(x)==Find(y) ) continue; fa[Find(x)]=Find(y); Add(x,y,_edges[i].pos); Add(y,x,_edges[i].pos); } } void DFS(int x,int from,int from_e) { static bool v[100100]; int i; if(v[x]) return ; v[x]=1;tree[x]=new abcd(0); if(from) { tree[n+from_e]=new abcd(from_e); tree[n+from_e]->fa=tree[from]; tree[x]->fa=tree[n+from_e]; } for(i=head[x];i;i=table[i].next) DFS(table[i].to,x,table[i].z); } inline int Query(abcd *x,abcd *y) { Move_To_Root(x); Access(y); Splay(y); return y->max_e; } void Insert(int pos) { abcd *x=tree[edges[pos].x]; abcd *y=tree[edges[pos].y]; if( Find_Root(x)==Find_Root(y) ) { int temp=Query(x,y); if(edges[temp].z<=edges[pos].z) return; Cut(tree[n+temp],tree[edges[temp].x]); Cut(tree[n+temp],tree[edges[temp].y]); } tree[n+pos]=new abcd(pos); Link(x,tree[n+pos]); Link(y,tree[n+pos]); } int main() { //freopen("2594.in","r",stdin); //freopen("2594.out","w",stdout); int i,x,y,z; cin>>n>>m>>q; for(i=1;i<=m;i++) { edges[i].x=Get_Int(); edges[i].y=Get_Int(); edges[i].z=Get_Int(); } sort(edges+1,edges+m+1); for(i=1;i<=q;i++) { queries[i].p=Get_Int(); queries[i].x=Get_Int(); queries[i].y=Get_Int(); if(queries[i].p==2) { int temp=lower_bound(edges+1,edges+m+1,make_pair(queries[i].x,queries[i].y) )-edges; queries[i].x=temp; v[temp]=1; } } Kruskal(); for(i=1;i<=n;i++) DFS(i,0,0); for(i=q;i;i--) { if(queries[i].p==1) stack[++top]=edges[Query(tree[queries[i].x],tree[queries[i].y])].z; else Insert(queries[i].x); } while(top) printf("%d\n",stack[top--]); }
BZOJ 2594 Wc2006 水管局长数据加强版 Link-Cut-Tree
标签:bzoj bzoj2594 link-cut-tree kruskal
原文地址:http://blog.csdn.net/popoqqq/article/details/41348549