zoukankan      html  css  js  c++  java
  • 洛谷4172 WC2006水管局长(LCT维护最小生成树)

    这个题和魔法森林感觉有很相近的地方啊
    同样也是维护一个类似最大边权最小的生成树

    但是不同的是,这个题是有(cut)和询问,两种操作....
    这可如何是好啊?

    我们不妨倒着来考虑,假设所有要(cut)的边全都不存在,倒序做这个问题,不就是相当于在支持(link)操作吗?

    那么就和之前的问题大致上是一样的了

    对于(u->v)
    如果(findroot(u)!=findroot(v)),就直接连边。
    如果(findroot(u)==findroot(v)),就判断原来两个点之间的路径的最大值是不是大于当前值,如果大于就替换

    直接上代码

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<cmath>
    #include<map>
    #include<set>
    #define mk make_pair
    
    using namespace std;
    
    inline int read()
    {
      int x=0,f=1;char ch=getchar();
      while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
      return x*f;
    }
    
    const int maxn = 4e5+1e2;
    
    struct Node{
    	int opt;
    	int x,y;
    };
    int ch[maxn][3];
    int siz[maxn];
    int fa[maxn];
    int mx[maxn],mxpos[maxn];
    int n,m;
    int rev[maxn];
    map<pair<int,int>,int> mp;
    int q;
    int x[maxn],y[maxn],w[maxn];
    int val[maxn];
    Node ymh[maxn];
    
    int son(int x)
    {
    	if (ch[fa[x]][0]==x) return 0;
    	else return 1;
    }
    
    bool notroot(int x)
    {
    	return ch[fa[x]][0]==x || ch[fa[x]][1]==x;
    }
    
    void update(int x)
    {
    	mx[x]=val[x];
    	mxpos[x]=x;
    	if (ch[x][0])
    	{
    		if (mx[ch[x][0]]>mx[x])
    		{
    			mx[x]=mx[ch[x][0]];
    			mxpos[x]=mxpos[ch[x][0]];
    		}
    	}
    	if (ch[x][1])
    	{
    		if (mx[ch[x][1]]>mx[x])
    		{
    			mx[x]=mx[ch[x][1]];
    			mxpos[x]=mxpos[ch[x][1]];
    		}
    	}
    }
    
    void reverse(int x)
    {
    	swap(ch[x][0],ch[x][1]);
    	rev[x]^=1;
    }
    
    void pushdown(int x)
    {
    	if (rev[x])
    	{
    		if (ch[x][0]) reverse(ch[x][0]);
    		if (ch[x][1]) reverse(ch[x][1]);
    		rev[x]=0;
    	}
    }
    
    void rotate(int x)
    {
    	int y=fa[x],z=fa[y];
    	int b=son(x),c=son(y);
    	if (notroot(y)) ch[z][c]=x;
    	fa[x]=z;
    	ch[y][b]=ch[x][!b];
    	fa[ch[x][!b]]=y;
    	ch[x][!b]=y;
    	fa[y]=x;
    	update(y);
    	update(x);
    }
    
    int st[maxn];
    
    void splay(int x)
    {
    	int y=x,cnt=0;
    	st[++cnt]=y;
    	while (notroot(y)) y=fa[y],st[++cnt]=y;
    	while (cnt) pushdown(st[cnt--]);
    	while (notroot(x))
    	{
    		int y=fa[x],z=fa[y];
    		int b=son(x),c=son(y);	
    		if (notroot(y))
    		{
    			if (b==c) rotate(y);
    			else rotate(x);
    		}
    		rotate(x);
    	}
    	update(x);
    }
    
    void access(int x)
    {
    	for (int y=0;x;y=x,x=fa[x])
    	{
    		splay(x);
    		ch[x][1]=y;
    		update(x);
    	}
    }
    
    void makeroot(int x)
    {
    	access(x);
    	splay(x);
    	reverse(x);
    }
    
    int findroot(int x)
    {
    	access(x);
    	splay(x);
    	while (ch[x][0])
    	{
    		pushdown(x);
    		x=ch[x][0];
    	}
    	return x;
    }
    
    void split(int x,int y)
    {
    	makeroot(x);
    	access(y);
    	splay(y);
    }
    
    void link(int x,int y)
    {
    	makeroot(x);
    	if (findroot(y)!=x) fa[x]=y;
    }
    
    void cut(int x,int y)
    {
    	split(x,y);
    	if (ch[x][0] || ch[x][1] || fa[x]!=y || ch[y][son(x)^1]) return;
    	fa[x]=ch[y][0]=0;
    }
    
    int vis[maxn];
    int ans[maxn];
    
    int main()
    {
       n=read(),m=read(),q=read();
       for (int i=1;i<=m;i++)
       {
       	  x[i]=read(),y[i]=read(),w[i]=read();
       	  val[i+n]=w[i];
       	  mp[mk(x[i],y[i])]=mp[mk(y[i],x[i])]=i;
       }
       for (int i=1;i<=q;i++)
       {
          ymh[i].opt=read();
          ymh[i].x=read();
          ymh[i].y=read();
          if (ymh[i].opt==2) vis[mp[mk(ymh[i].x,ymh[i].y)]]=1;
       }
       for (int i=1;i<=m;i++)
       {
       	 if (vis[i]) continue;
       	 if (findroot(x[i])!=findroot(y[i]))
       	 {
       	    link(x[i],i+n);
       	    link(y[i],i+n);
       	    mp[mk(x[i],y[i])]=mp[mk(y[i],x[i])]=i+n;
    	 }
    	 else
    	 {
    	 	split(x[i],y[i]);
    	 	int now =mxpos[y[i]];
    	 	if (mx[y[i]]<w[i]) continue;
    	 	cut(x[now-n],now);
    	 	cut(y[now-n],now);
    	 	mp[mk(x[now-n],y[now-n])]=mp[mk(y[now-n],x[now-n])]=0;
    	 	link(x[i],i+n);
    	 	link(y[i],i+n);
    	 	mp[mk(x[i],y[i])]=mp[mk(y[i],x[i])]=i+n;
    	 }
       }
       int tmp=0;
       
       for (int j=q;j>=1;j--)
       {
       	  
       	  if (ymh[j].opt==1)
       	  {
       	  	 split(ymh[j].x,ymh[j].y);
       	  	 ans[++tmp]=mx[ymh[j].y];
       	  	 //printf("%d
    ",mx[ymh[j].y]);
    	  }
    	  else
    	  {
    	  	 int i=mp[mk(ymh[j].x,ymh[j].y)];
    	     if (findroot(x[i])!=findroot(y[i]))
       	      {
       	       link(x[i],i+n);
       	       link(y[i],i+n);
       	       //mp[mk(x[i],y[i])]=mp[mk(y[i],x[i])]=i+n;
    	      }
    	     else
    	     {
    	 	   split(x[i],y[i]);
    	 	   int now =mxpos[y[i]];
    	 	   if (mx[y[i]]<val[i+n]) continue;
    	 	   cut(x[now-n],now);
    	 	   cut(y[now-n],now);
    	 	   //mp[mk(x[now-n],y[now-n])]=mp[mk(y[now-n],x[now-n])]=0;
    	 	   link(x[i],i+n);
    	 	   link(y[i],i+n);
    	 	   //mp[mk(x[i],y[i])]=mp[mk(y[i],x[i])]=i+n;
    	      }	 
    	  }
       }
       
       for (int i=tmp;i>=1;i--)
       {
       	 printf("%d
    ",ans[i]);
       }
       return 0;
    }
    
    
  • 相关阅读:
    Java IO流之缓冲流
    Java文件流之练习
    PHP使用mkdir创建多级目录的方法
    PHP中file_exists()判断中文文件名无效的解决方法
    如何用CURL将文件下载到本地指定文件夹
    解决Maximum execution time of 120 seconds exceeded
    批量插入数据insert into select示例
    PHP数据结构之五 栈的PHP的实现和栈的基本操作
    PHP数据结构之四 一元多项式的相加PHP单链实现
    PHP数据结构之三 线性表中的单链表的PHP实现
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10161411.html
Copyright © 2011-2022 走看看