BZOJ3669: [Noi2014]魔法森林
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3669: [Noi2014]魔法森林相关的知识,希望对你有一定的参考价值。
高级数据结构学傻系列
正解似乎是最短路xjb搞,但是用LCT瞎搞搞也是很吼啊。
从贪心开始,按照每条边a的大小随意sort一下。
对于每个边,我们check两点的联通性,如果联通的话取b最大的值,如果大于当前边的b的话就就删除最大边,把这条边加进去。
如果不连通的话直接添加即可。
LCT滋次这些操作,所以大力LCT即可。
//BZOJ 3669 //by Cydiater //2017.2.16 #include <iostream> #include <queue> #include <map> #include <cstring> #include <string> #include <iomanip> #include <ctime> #include <cstdlib> #include <cstdio> #include <iomanip> #include <algorithm> #include <bitset> #include <set> #include <vector> #include <complex> using namespace std; #define ll long long #define up(i,j,n) for(int (i)=(j);(i)<=(n);(i)++) #define down(i,j,n) for(int (i)=(j);(i)>=(n);(i)--) #define cmax(a,b) a=max(a,b) #define cmin(a,b) a=min(a,b) #define FILE "magicalforest" const int MAXN=1e6+5; const int oo=0x3f3f3f3f; inline int read(){ char ch=getchar();int x=0,f=1; while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} return x*f; } int N,M,len=0,ans=oo; struct edge{ int x,y,a,b; }e[MAXN]; namespace LCT{ struct SplayTree{ int son[2],Max,val,fa,tag,id; void clear(){son[0]=son[1]=Max=val=fa=0;} }t[MAXN]; inline int isrt(int k){return t[k].fa==0||(t[t[k].fa].son[0]!=k&&t[t[k].fa].son[1]!=k);} inline int get(int k){return t[t[k].fa].son[1]==k;} inline void rev(int k){ if(!k)return; swap(t[k].son[0],t[k].son[1]); t[k].tag^=1; } inline void reload(int k){ if(!k)return; t[k].Max=t[k].val;t[k].id=k; int s1=t[k].son[0],s2=t[k].son[1]; if(t[s1].Max>t[k].Max){ t[k].Max=t[s1].Max; t[k].id=t[s1].id; } if(t[s2].Max>t[k].Max){ t[k].Max=t[s2].Max; t[k].id=t[s2].id; } } inline void Pushdown(int k){ if(!k)return; if(t[k].tag){ rev(t[k].son[0]);rev(t[k].son[1]); t[k].tag^=1; } } inline void rotate(int k){ int old=t[k].fa,oldf=t[old].fa,which=get(k); if(!isrt(old))t[oldf].son[t[oldf].son[1]==old]=k; t[old].son[which]=t[k].son[which^1];t[t[old].son[which]].fa=old; t[k].son[which^1]=old;t[old].fa=k;t[k].fa=oldf;t[0].clear(); reload(old);reload(k); } int stack[MAXN],top=0; inline void splay(int k){ top=0;stack[++top]=k; for(int tmp=k;!isrt(tmp);tmp=t[tmp].fa){ stack[++top]=t[tmp].fa; } while(top)Pushdown(stack[top--]); while(!isrt(k)){ int fa=t[k].fa; if(!isrt(fa))rotate(get(fa)==get(k)?fa:k); rotate(k); } } inline void access(int k){ int tmp=0; while(k){ splay(k);t[k].son[1]=tmp; reload(k);tmp=k;k=t[k].fa; } } void mrt(int k){ access(k);splay(k);rev(k); } int grt(int k){ access(k);splay(k); while(t[k].son[0])k=t[k].son[0]; return k; } void Link(int x,int y){ mrt(x);t[x].fa=y; } void Cut(int x,int y){ mrt(x);access(y);splay(y);t[y].son[0]=t[x].fa=0; reload(y); } int col(int x,int y){ mrt(x);access(y);splay(y); return t[y].id; } } int cnt; namespace solution{ inline bool cmp(edge x,edge y){return x.a<y.a;} void Prepare(){ N=read();M=read(); cnt=N; up(i,1,M){ int x=read(),y=read(),a=read(),b=read(); e[++len]=(edge){x,y,a,b}; } sort(e+1,e+M+1,cmp); } void Solve(){ up(i,1,M){ cnt++; int x=e[i].x,y=e[i].y,a=e[i].a,b=e[i].b; if(LCT::grt(x)!=LCT::grt(y)){ LCT::t[cnt].Max=b; LCT::t[cnt].val=b; LCT::t[cnt].id=cnt; LCT::Link(x,cnt); LCT::Link(cnt,y); } else{ int id=LCT::col(x,y); if(LCT::t[id].val<=b)continue; LCT::Cut(e[id-N].x,id); LCT::Cut(e[id-N].y,id); LCT::t[cnt].Max=b; LCT::t[cnt].val=b; LCT::t[cnt].id=cnt; LCT::Link(x,cnt); LCT::Link(cnt,y); } if(LCT::grt(1)==LCT::grt(N)){ int id=LCT::col(1,N); cmin(ans,a+LCT::t[id].val); } } if(ans==oo)ans=-1; cout<<ans<<endl; } } int main(){ using namespace solution; Prepare(); Solve(); return 0; }
以上是关于BZOJ3669: [Noi2014]魔法森林的主要内容,如果未能解决你的问题,请参考以下文章