bzoj3669: [Noi2014]魔法森林 LCT
来源:互联网 发布:淘宝网触屏版下载安装 编辑:程序博客网 时间:2024/05/03 16:49
题解:
暴力的想法是枚举a的上界,做b的最小生成树。
而且有一个比较显然的性质是:
如果可以在一个生成树中加入一条边,使得树的总权值更小,那么一定是(设这条边连接 x,y)x--y原路径上的最大权值<这条边的权值
删掉这条边,加上新边。
那么我们只需要用LCT,维护点与点之间的最大权值,将边以a排序,一条一条试图往里面加即可。
如果x,y不连通直接加入,否则按上述查询x,y的最大值,比较。
然后每次都更新一下答案。
需要注意的是,边权可以转化成点权,我们从x,y各向这个新点连边、删边即可。
暴力的想法是枚举a的上界,做b的最小生成树。
而且有一个比较显然的性质是:
如果可以在一个生成树中加入一条边,使得树的总权值更小,那么一定是(设这条边连接 x,y)x--y原路径上的最大权值<这条边的权值
删掉这条边,加上新边。
那么我们只需要用LCT,维护点与点之间的最大权值,将边以a排序,一条一条试图往里面加即可。
如果x,y不连通直接加入,否则按上述查询x,y的最大值,比较。
然后每次都更新一下答案。
需要注意的是,边权可以转化成点权,我们从x,y各向这个新点连边、删边即可。
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <cmath>using namespace std;int INF=0x3f3f3f3f;#define maxn 160000int getint(){ char c;int res; while(c=getchar(),c<'0'||c>'9'); res=c-'0'; while(c=getchar(),c>='0'&&c<='9') res=res*10+c-'0'; return res;}struct node{int x,y,a,b;}e[maxn];int n,m,ans,fa[maxn],tr[maxn][2],f[maxn],next[maxn],mx[maxn],v[maxn];bool rev[maxn];bool isroot(int x){ return (tr[fa[x]][0]!=x)&&(tr[fa[x]][1]!=x);}inline void pushup(int x){ mx[x]=x; if(v[mx[tr[x][0]]]>v[mx[x]]) mx[x]=mx[tr[x][0]]; if(v[mx[tr[x][1]]]>v[mx[x]]) mx[x]=mx[tr[x][1]];}void rotate(int x){ int l,r,y,z; y=fa[x];z=fa[y]; if(tr[y][0]==x) l=0; else l=1;r=l^1; if(!isroot(y)) { if(tr[z][0]==y) tr[z][0]=x; else tr[z][1]=x; } fa[x]=z;fa[y]=x;fa[tr[x][r]]=y; tr[y][l]=tr[x][r];tr[x][r]=y; pushup(y);pushup(x);}void pushdown(int x){ if(!isroot(x)) pushdown(fa[x]); if(rev[x]) { rev[x]^=1;rev[tr[x][1]]^=1;rev[tr[x][0]]^=1; swap(tr[x][0],tr[x][1]); }}void splay(int x){ pushdown(x); int y,z; while(!isroot(x)) { y=fa[x];z=fa[y]; if(!isroot(y)) { if((tr[y][0]==x)^(tr[z][0]==y)) rotate(x); else rotate(y); } rotate(x); }}void access(int x){ int t=0; while(x) { splay(x); tr[x][1]=t; pushup(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;splay(x);}void cut(int x,int y){ makeroot(x);access(y);splay(y); fa[x]=0;tr[y][0]=0;}int getf(int x){ return f[x]==x?x:f[x]=getf(f[x]);}inline int ask(int x,int y){ makeroot(x);access(y);splay(y);return mx[y];}bool cmp(node aa,node bb){ return aa.a<bb.a;}int main(){ n=getint();m=getint(); for(int i=1;i<=n;i++) f[i]=i; for(int i=1;i<=m;i++) { e[i].x=getint();e[i].y=getint(); e[i].a=getint();e[i].b=getint(); } int r1,r2,x,y,tmp;ans=INF; sort(e+1,e+1+m,cmp); for(int i=1;i<=m;i++) { mx[i]=i+n; v[i+n]=e[i].b; } for(int i=1;i<=m;i++) { x=e[i].x;y=e[i].y; r1=getf(x);r2=getf(y); if(r1!=r2) { f[r1]=r2; link(x,n+i);link(y,n+i); } else { tmp=ask(x,y); if(e[i].b<v[tmp]) { cut(e[tmp-n].x,tmp);cut(e[tmp-n].y,tmp); link(x,n+i);link(y,n+i); } } if(getf(1)==getf(n))ans=min(ans,v[ask(1,n)]+e[i].a); } printf("%d\n",ans==INF?-1:ans); return 0;}
0 0
- bzoj3669: [Noi2014]魔法森林 LCT
- [BZOJ3669][Noi2014]魔法森林 && LCT
- 【bzoj3669】[Noi2014]魔法森林 LCT
- 【BZOJ3669】【NOI2014】魔法森林 LCT
- [BZOJ3669][UOJ#3][Noi2014][LCT]魔法森林
- BZOJ3669: [Noi2014]魔法森林(LCT)
- [BZOJ3669][NOI2014]魔法森林(LCT)
- BZOJ3669 [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- [BZOJ3669][Noi2014]魔法森林
- 【NOI2014】【BZOJ3669】魔法森林
- [bzoj3669][NOI2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669 [Noi2014]魔法森林
- 【NOI2014】bzoj3669 魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- Curl多线程|CurlMulti
- android application
- Linux 命令2-cd命令
- 排序应该在数据库中还是应用程序中?
- Linux 命令3-pwd命令
- bzoj3669: [Noi2014]魔法森林 LCT
- 李白打酒
- Cocos2d-x3.3 Physics物理引擎模块解决了刚体穿透问题------沈大海
- 科学,宗教和信仰,以及神
- hdu1166
- 辛星解读Redis中的RDB持久化方式
- 活用IoT的下一代的住房管理系统
- C++空指针
- Linux 命令4-mkdir命令