首页 > 代码库 > BZOJ3669: [Noi2014]魔法森林
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]魔法森林
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。