洛谷4172 WC2006水管局长(LCT维护最小生成树)

题目链接

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

但是不同的是,这个题是有 c u t cut 和询问,两种操作…
这可如何是好啊?

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

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

对于 u > v u->v
如果 f i n d r o o t ( u ) ! = f i n d r o o t ( v ) findroot(u)!=findroot(v) ,就直接连边。
如果 f i n d r o o t ( u ) = = f i n d r o o t ( 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\n",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\n",ans[i]);
   }
   return 0;
}

猜你喜欢

转载自blog.csdn.net/y752742355/article/details/84483532