LCT——BZOJ3669/Luogu2387 [Noi2014]魔法森林
2017-05-22 21:39
253 查看
题面:BZOJ3669 Luogu2387
LCT维护动态最小生成树
具体怎么操作呢,如果当前加边后树中形成了环,那么就把环上边权最大的边删掉,再把这条边加进去(当然啦如果这条边比环里的边都大就不要加)
这就是维护动态最小生成树,这些操作都可以用LCT来解决
LCT维护边权最大值(只不过维护的时候要记录的是编号)
然后最后答案的话在每次操作之后都询问一下从1到n的最大边权
这个也只要直接access就好了
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; }
相关文章推荐
- BZOJ_P3669&Codevs_P3314 [NOI2014]魔法森林(LCT+Kruskal)
- 【BZOJ】【P3669】【NOI2014】【魔法森林】【题解】【LCT】
- [bzoj] 3669 NOI2014 魔法森林 || LCT
- bzoj3669: [Noi2014]魔法森林 lct版
- BZOJ 3669: [Noi2014]魔法森林 LCT
- ☆ [NOI2014] 魔法森林 「LCT动态维护最小生成树」
- 【BZOJ】3669: [Noi2014]魔法森林(lct+特殊的技巧)
- NOI2014 魔法森林 LCT维护MST
- 【BZOJ 3669】 [Noi2014]魔法森林 LCT维护动态最小生成树
- BZOJ_3669_[Noi2014]魔法森林_LCT
- bzoj 3669: [Noi2014]魔法森林(并查集+LCT)
- bzoj 3669 NOI2014 魔法森林 [LCT]
- NOI2014-魔法森林(LCT)
- 【bzoj3669】[Noi2014]魔法森林 LCT
- 【BZOJ3669】[Noi2014]魔法森林 LCT
- 【BZOJ3669】【NOI2014】魔法森林 LCT
- NOI 2014 魔法森林 LCT
- BZOJ 3669 [Noi2014]魔法森林 | LCT
- BZOJ3669(NOI2014):魔法森林 (LCT维护最小生成树)
- [BZOJ]3669: [Noi2014]魔法森林 lct