zoukankan      html  css  js  c++  java
  • WC2006 水管局长数据加强版

    水管局长

    SC省MY市有着庞大的地下水管网络,嘟嘟是MY市的水管局长(就是管水管的啦),嘟嘟作为水管局长的工作就是:每天供水公司可能要将一定量的水从x处送往y处,嘟嘟需要为供水公司找到一条从A至B的水管的路径,接着通过信息化的控制中心通知路径上的水管进入准备送水状态,等到路径上每一条水管都准备好了,供水公司就可以开始送水了。嘟嘟一次只能处理一项送水任务,等到当前的送水任务完成了,才能处理下一项。

    在处理每项送水任务之前,路径上的水管都要进行一系列的准备操作,如清洗、消毒等等。嘟嘟在控制中心一声令下,这些水管的准备操作同时开始,但由于各条管道的长度、内径不同,进行准备操作需要的时间可能不同。供水公司总是希望嘟嘟能找到这样一条送水路径,路径上的所有管道全都准备就绪所需要的时间尽量短。嘟嘟希望你能帮助他完成这样的一个选择路径的系统,以满足供水公司的要求。另外,由于MY市的水管年代久远,一些水管会不时出现故障导致不能使用,你的程序必须考虑到这一点。

    不妨将MY市的水管网络看作一幅简单无向图(即没有自环或重边):水管是图中的边,水管的连接处为图中的结点。

    N ≤ 100000
    M ≤ 1000000
    Q ≤ 100000

    分析

    倒着做,把删边变成加边。

    先跑出来最小生成树,根据树建出lct。剩下的边显然没用扔掉。

    然后我们每一次加边时考虑树上两点间的权值,假如更劣我们删除路径上边权最大,加入当前边即可。

    显然这些用LCT维护即可。时间复杂度(O(N+M log N+Qlog N))


    说一下维护的具体方法。

    首先是用到把边转化成点,方便LCT连边删边和统计的套路。

    LCT合并信息的时候统计权值最大的点的编号,这样外部查询一条链的时候就能快速定位。

    注意对输入的边找编号等等操作的细节即可。

    co int N=1e5+1,M=1e6+1;
    int n,m,Q;
    namespace T{
    	int fa[N+M],ch[N+M][2],val[N+M],mp[N+M],st[N+M]; // edit 1:memory
    	bool rev[N+M];
    #define lc ch[x][0]
    #define rc ch[x][1]
    	bool nroot(int x){
    		return ch[fa[x]][0]==x||ch[fa[x]][1]==x;
    	}
    	void pushup(int x){
    		mp[x]=x;
    		if(val[mp[lc]]>val[mp[x]]) mp[x]=mp[lc];
    		if(val[mp[rc]]>val[mp[x]]) mp[x]=mp[rc];
    	}
    	void rever(int x){
    		std::swap(lc,rc),rev[x]^=1;
    	}
    	void pushdown(int x){
    		if(rev[x]){
    			if(lc) rever(lc);
    			if(rc) rever(rc);
    			rev[x]=0;
    		}
    	}
    	void rotate(int x){
    		int y=fa[x],z=fa[y],d=ch[y][1]==x,w=ch[x][!d];
    		if(nroot(y)) ch[z][ch[z][1]==y]=x;ch[x][!d]=y,ch[y][d]=w;
    		if(w) fa[w]=y;fa[y]=x,fa[x]=z;
    		pushup(y);
    	}
    	void splay(int x){
    		int y=x,z=0;
    		st[++z]=y;
    		while(nroot(y)) st[++z]=y=fa[y];
    		while(z) pushdown(st[z--]);
    		while(nroot(x)){
    			y=fa[x],z=fa[y];
    			if(nroot(y)) rotate(ch[y][0]==x^ch[z][0]==y?x:y);
    			rotate(x);
    		}
    		pushup(x);
    	}
    	void access(int x){
    		for(int y=0;x;x=fa[y=x])
    			splay(x),rc=y,pushup(x);
    	}
    	void makeroot(int x){
    		access(x),splay(x),rever(x);
    	}
    	void link(int x,int y){
    		makeroot(x),fa[x]=y;
    	}
    	void cut(int x,int y){
    		makeroot(x),access(y),splay(y),ch[y][0]=fa[x]=0;
    	}
    	int query(int x,int y){
    		makeroot(x),access(y),splay(y);return mp[y];
    	}
    }
    struct edge{
    	int x,y,w,id,del;
    }e[M];
    bool cw(co edge&a,co edge&b){
    	return a.w<b.w;
    }
    bool cxy(co edge&a,co edge&b){
    	return a.x^b.x?a.x<b.x:a.y<b.y;
    }
    bool cid(co edge&a,co edge&b){
    	return a.id<b.id;
    }
    int find(int x,int y){
    	int l=1,r=m;
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(e[mid].x<x||(e[mid].x==x&&e[mid].y<y)) l=mid+1;
    		else if(e[mid].x==x&&e[mid].y==y) return mid;
    		else r=mid-1;
    	}
    }
    struct quiz{
    	int f,x,y,ans,id;
    }q[N];
    namespace D{
    	int fa[N];
    	int find(int x){
    		return x==fa[x]?x:fa[x]=find(fa[x]);
    	}
    }
    int main(){
    //	freopen("BZOJ2594.in","r",stdin);
    //	freopen(".out","w",stdout);
    	read(n),read(m),read(Q);
    	for(int i=1;i<=n;++i) D::fa[i]=i;
    	for(int i=1;i<=m;++i){
    		read(e[i].x),read(e[i].y),read(e[i].w);
    		if(e[i].x>e[i].y) std::swap(e[i].x,e[i].y);
    	}
    	std::sort(e+1,e+m+1,cw);
    	for(int i=1;i<=m;++i)
    		e[i].id=i,T::val[n+i]=e[i].w,T::mp[n+i]=n+i;
    	std::sort(e+1,e+m+1,cxy);
    	for(int i=1;i<=Q;++i){
    		read(q[i].f),read(q[i].x),read(q[i].y);
    		if(q[i].f==2){
    			if(q[i].x>q[i].y) std::swap(q[i].x,q[i].y);
    			int t=find(q[i].x,q[i].y);
    			e[t].del=1,q[i].id=e[t].id;
    		}
    	}
    	std::sort(e+1,e+m+1,cid);
    	int tot=0;
    	for(int i=1;i<=m;++i) if(!e[i].del){
    		int x=e[i].x,y=e[i].y;
    		int fx=D::find(x),fy=D::find(y);
    		if(fx!=fy){
    			D::fa[fx]=fy;
    			T::link(x,i+n),T::link(y,i+n);
    			if(++tot==n-1) break;
    		}
    	}
    	for(int i=Q;i;--i){
    		if(q[i].f==1) q[i].ans=T::val[T::query(q[i].x,q[i].y)];
    		else{
    			int x=q[i].x,y=q[i].y,k=q[i].id,t=T::query(x,y);
    			if(e[k].w<T::val[t]){
    				T::cut(e[t-n].x,t),T::cut(e[t-n].y,t);
    				T::link(x,k+n),T::link(y,k+n);
    			}
    		}
    	}
    	for(int i=1;i<=Q;++i) if(q[i].f==1)
    		printf("%d
    ",q[i].ans);
    	return 0;
    }
    
  • 相关阅读:
    Dell FC Switch zone configuration
    RMAN参考使用手册[转载]
    CentOS下SVN简介、下载、安装
    教你制作启动U盘 用U盘装系统(转载)
    RMAN简明使用手册[转载]
    控制文件和重做日志文件(1)[转载)
    RMAN快速入门指南[转载]
    Dell服务转移
    BE Learing 8 异常及解决办法
    10g rman备份恢复案例[转载]
  • 原文地址:https://www.cnblogs.com/autoint/p/10413048.html
Copyright © 2011-2022 走看看