您的位置:首页 > 其它

bzoj 2594 水管局长 | LCT | 最小生成树

2015-11-16 10:39 302 查看
将所有操作逆序,删边就成了加边,做LCT维护最小生成树即可。把边i表示成点i+n,那么加一条边x,y就相当于link(x,i+n) link(y,i+n) 删边同理。我的release写成了“上放标记”了 TAT
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>

#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 2000010
using namespace std;
struct yts { int x,y,l,id,del;} e
;
struct QQ { int x,y,pos,opt;} q[200010];
int father
;
int n,m;
int ch
[2],fa
,rev
,mx
,po
,dt
,que
;
int ans[100010];

int read()
{
    char ch = getchar();
    for ( ; ch > '9' || ch < '0'; ch = getchar());
    int tmp = 0;
    for ( ; '0' <= ch && ch <= '9'; ch = getchar())
      tmp = tmp * 10 + int(ch) - 48;
    return tmp;
} 
bool cmpid(yts a,yts b) { return a.id<b.id;}
bool cmp(yts a,yts b) { return a.l<b.l; }
bool operator < (yts a,yts b) { return a.x==b.x?a.y<b.y:a.x<b.x; }
int find_path(int x,int y)
{
	yts nd; nd.x=x; nd.y=y;
	int l=1,r=m;
	while (l!=r)
	{
		int mid=(l+r)>>1;
		if (e[mid]<nd) l=mid+1; else r=mid;
	}
	return l;
}
int find(int x) { return father[x]==x?x:father[x]=find(father[x]);}
//-----------------------------------------------------------------

bool isroot(int x) { if (ch[fa[x]][0]==x||ch[fa[x]][1]==x) return 0; else return 1; }
bool dir(int x) { return ch[fa[x]][1]==x;}
void release(int i)
{
	if (rev[i])
	{
		rev[i]=0;
		swap(ch[i][0],ch[i][1]);
		if (ch[i][0]) rev[ch[i][0]]^=1;
		if (ch[i][1]) rev[ch[i][1]]^=1;
	}
}

void update(int i)
{
	int l=ch[i][0],r=ch[i][1];
	mx[i]=dt[i]; po[i]=i;
	if (l&&mx[i]<mx[l]) { mx[i]=mx[l]; po[i]=po[l]; }
	if (r&&mx[i]<mx[r]) { mx[i]=mx[r]; po[i]=po[r]; }
}

void rotate(int x)
{
	int y=fa[x],z=fa[y],b=dir(x),c=dir(y),a=ch[x][!b];
	if (!isroot(y)) ch[z][c]=x;
	if (a) fa[a]=y; fa[y]=x; fa[x]=z;
	ch[x][!b]=y; ch[y][b]=a;
	update(y); update(x);
}

void splay(int x)
{
	int w=0; que[++w]=x;
	for (int i=x;!isroot(i);i=fa[i]) que[++w]=fa[i];
	for (int i=w;i;i--) release(que[i]);
	while (!isroot(x))
	{
		int y=fa[x],z=fa[y];
		if (isroot(y)) rotate(x);
		else
		{
			if (dir(x)==dir(y)) { rotate(y); rotate(x); }
			  else { rotate(x); rotate(x); }
		}
	}
}

void access(int x)
{
	int t=0;
	while (x)
	{
		splay(x);
		ch[x][1]=t;
		update(x);
		t=x; x=fa[x];
	}
}

void makeroot(int x)
{
	access(x); splay(x); rev[x]^=1;
}

void link(int x,int y)
{
	makeroot(x); fa[x]=y;
}

void cut(int x,int y)
{
	makeroot(x); access(y); splay(y);
	fa[x]=ch[y][0]=0; 
	update(x); update(y);
}

int query(int x,int y)
{
	makeroot(x); access(y); splay(y);
	return po[y];
}

//-----------------------------------------------------------------
int main()
{
	//freopen("data.in","r",stdin); freopen("data.out","w",stdout);
	int Q;
	n=read(),m=read(),Q=read();
	for (int i=1;i<=n;i++) dt[i]=mx[i]=0;
	for (int i=1;i<=m;i++)
	{
		e[i].x=read(); e[i].y=read(); e[i].l=read();
		if (e[i].x>e[i].y) swap(e[i].x,e[i].y);
		e[i].id=i; dt[i+n]=mx[i+n]=e[i].l;
	}
	sort(e+1,e+m+1);
	for (int i=1;i<=Q;i++)
	{
		int opt=read(),x=read(),y=read();
		if (x>y) swap(x,y);
		if (opt==1)
		{
			q[i].x=x; q[i].y=y; q[i].opt=1;
		}
		else
		{
			int p=find_path(x,y);
			e[p].del=1;
			q[i].x=x; q[i].y=y; q[i].opt=2; q[i].pos=e[p].id;
		}
	}
	sort(e+1,e+m+1,cmp);
	for (int i=1;i<=n;i++) father[i]=i;
	for (int i=1;i<=m;i++)
	{
		if (e[i].del) continue;
		int x=e[i].x,y=e[i].y;
		int f1=find(x),f2=find(y);
		if (f1!=f2)
		{
			father[f1]=f2;
			int p=e[i].id;
			link(x,p+n); link(y,p+n);
		}
	}
	sort(e+1,e+m+1,cmpid);
	int ww=0;
	for (int i=Q;i;i--)
	{
		if (q[i].opt==1) ans[++ww]=dt[query(q[i].x,q[i].y)];
		else
		{
			int id=q[i].pos,x=q[i].x,y=q[i].y;
			int p=query(x,y);
			if (dt[p]>e[id].l)
			{
				cut(x,p); cut(y,p);
				link(x,id+n); link(y,id+n);
			}
		}
	}
	for (int i=ww;i;i--) printf("%d\n",ans[i]);
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: