您的位置:首页 > 其它

LCT——BZOJ3669/Luogu2387 [Noi2014]魔法森林

2017-05-22 21:39 253 查看
题面:BZOJ3669 Luogu2387

LCT维护动态最小生成树

具体怎么操作呢,如果当前加边后树中形成了环,那么就把环上边权最大的边删掉,再把这条边加进去(当然啦如果这条边比环里的边都大就不要加)

这就是维护动态最小生成树,这些操作都可以用LCT来解决

LCT维护边权最大值(只不过维护的时候要记录的是编号)

然后最后答案的话在每次操作之后都询问一下从1到n的最大边权

这个也只要直接access就好了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstdlib>
#include<string>
#include<ctime>
#include<queue>
#include<climits>
using namespace std;
struct ppap{int x,y,a,b;}a[100001];
inline bool cmp(ppap a,ppap b){return a.a<b.a;}
int t[200001][2],fa[200001],la[200001];
int n,m,zh[200001],v[200001],s[200001];
inline void pushup(int x){
s[x]=x;if(v[s[t[x][0]]]>v[s[x]])s[x]=s[t[x][0]];
if(v[s[t[x][1]]]>v[s[x]])s[x]=s[t[x][1]];
}
inline void pushdown(int x){
if(la[x]){
swap(t[x][1],t[x][0]);
la[t[x][1]]^=1;la[t[x][0]]^=1;
}
la[x]=0;
}
inline bool rt(int x){
return t[fa[x]][0]!=x&&t[fa[x]][1]!=x;
}
inline void turn(int x){
int y=fa[x],z=fa[y],l=(x!=t[fa[x]][0]),r=(y!=t[fa[y]][0]);
int p=t[x][l^1];
if(!rt(y))t[z][r]=x;
fa[p]=y;fa[x]=z;t[x][l^1]=y;fa[y]=x;t[y][l]=p;
pushup(y);pushup(x);
}
inline void splay(int x){
int i=x,y,z;for(;!rt(i);i=fa[i])zh[++zh[0]]=i;
zh[++zh[0]]=i;while(zh[0])pushdown(zh[zh[0]--]);
while(!rt(x)){
y=fa[x];z=fa[y];
if(!rt(y)){
if((t[y][0]==x)^(t[z][0]==y))turn(x);
else turn(y);
}
turn(x);
}
}
inline void access(int x){
int p=0;
while(x){
splay(x);t[x][1]=p;
p=x;pushup(x);x=fa[x];
}
}
inline void chrt(int x){
access(x);splay(x);la[x]^=1;
}
inline void link(int x,int y){
chrt(x);fa[x]=y;
}
inline void cut(int x,int y){
chrt(x);access(y);splay(y);
t[y][0]=fa[x]=0;pushup(y);
}
inline int askrt(int x){
access(x);splay(x);int p=x;pushdown(x);
while(t[p][0])p=t[p][0],pushdown(p);
return p;
}
int main()
{
scanf("%d%d",&n,&m);int ans=1e9;
for(int i=1;i<=m;i++)scanf("%d%d%d%d",&a[i].x,&a[i].y,&a[i].a,&a[i].b);
sort(a+1,a+m+1,cmp);
for(int i=1;i<=m;i++){
int X=a[i].x,Y=a[i].y,A=a[i].a,B=a[i].b;
if(askrt(X)==askrt(Y)){
chrt(X);access(Y);splay(Y);int p=s[Y];
if(v[p]>B)cut(p,a[p-n].x),cut(p,a[p-n].y);
else{
if(askrt(1)==askrt(n)){
chrt(1);access(n);splay(n);
ans=min(ans,A+v[s
]);
}
continue;
}
}
v[n+i]=B;s[n+i]=n+i;link(X,n+i);link(Y,n+i);
if(askrt(1)==askrt(n)){
chrt(1);access(n);splay(n);
ans=min(ans,A+v[s
]);
}
}
if(ans==1e9)puts("-1");
else printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息