bzoj 3669: [Noi2014]魔法森林
来源:互联网 发布:手机拨号软件 编辑:程序博客网 时间:2024/05/18 03:03
题意:
在无向图中找一条1到n的路径,使其中
题解:
lct+类似最小生成树。
首先假如这只有一个参数,那么就是水题了。
但是有两个参数,考虑按a值排序,每次将a值相同的边加进去,然后计算答案。
那么怎么知道此时1到n的最小的最大b值呢?
用lct维护一个类似最小生成树的东西,对于一条边,都看作一个点,边权做点权,向他原来连接的点连边。
当加入时,先看看是否成环,不成环直接加上就好了。
当成环的时候,那么就找到这条链上的最大权的点(lct维护),假如大于当前加的点,那就cut掉,link新点,否则保留原来的。
然后没有然后了。
code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;struct trnode{ int fa,son[2],rev,d,c;}tr[150010];int mymax(int x,int y){return tr[x].d>tr[y].d?x:y;}void update(int x){ int lc=tr[x].son[0],rc=tr[x].son[1]; tr[x].c=mymax(tr[lc].c,tr[rc].c); tr[x].c=mymax(tr[x].c,x); if(tr[x].rev) { tr[x].rev=0;tr[lc].rev^=1;tr[rc].rev^=1; swap(tr[x].son[0],tr[x].son[1]); }}bool is_root(int x){ int fa=tr[x].fa; if(tr[fa].son[0]==x||tr[fa].son[1]==x) return false; return true;}void pushdown(int x){ if(!is_root(x)) pushdown(tr[x].fa); update(x);}void rotate(int x){ int y=tr[x].fa,z=tr[y].fa,w,R,r; w=(tr[y].son[0]==x); R=y;r=tr[x].son[w]; tr[R].son[1-w]=r; if(r) tr[r].fa=R; R=z;r=x; if(!is_root(y)) tr[R].son[tr[z].son[1]==y]=r; if(r) tr[r].fa=R; R=x;r=y; tr[R].son[w]=r; if(r) tr[r].fa=R; update(y);update(x);}void splay(int x){ pushdown(x); while(!is_root(x)) { int y=tr[x].fa,z=tr[y].fa; if(is_root(y)) rotate(x); else if((tr[z].son[0]==y)==(tr[y].son[0]==x)) rotate(y),rotate(x); else rotate(x),rotate(x); }}void access(int x){ int last=0; while(x) { splay(x); tr[x].son[1]=last; update(x); last=x;x=tr[x].fa; }}void make_root(int x){ access(x); splay(x); tr[x].rev^=1;}void split(int x,int y){ make_root(x); access(y); splay(y);}void link(int x,int y){ make_root(x); tr[x].fa=y;}void cut(int x,int y){ split(x,y); tr[x].fa=tr[y].son[0]=0; update(y);}int find_root(int x){ access(x); splay(x); while(tr[x].son[0]) x=tr[x].son[0]; return x;}int n,m;struct node{ int x,y,a,b;}a[100010];int ans=-1;bool cmp(node a,node b){return a.a<b.a;}void cc(int &x,int y){if(x==-1) x=y;x=min(x,y);}void add(node b,int num){ int x=b.x,y=b.y,tx=find_root(x),ty=find_root(y); tr[num].d=b.b; if(tx!=ty) link(x,num),link(y,num); else { split(x,y); int c=tr[y].c; if(tr[c].d<=b.b) return; cut(c,a[c-n].x);cut(c,a[c-n].y); link(x,num);link(y,num); }}void solve(int a){ int tx=find_root(1),ty=find_root(n); if(tx==ty) split(1,n),cc(ans,a+tr[tr[n].c].d);}int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f;}int main(){ n=read();m=read(); for(int i=1;i<=m;i++) a[i].x=read(),a[i].y=read(),a[i].a=read(),a[i].b=read(); sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { add(a[i],i+n); if(i==m||a[i+1].a!=a[i].a) solve(a[i].a); } printf("%d",ans);}
阅读全文
2 0
- bzoj 3669: [Noi2014]魔法森林
- bzoj 3669: [Noi2014]魔法森林
- bzoj 3669: [Noi2014]魔法森林
- BZOJ 3669: [Noi2014]魔法森林
- BZOJ 3669: [Noi2014]魔法森林
- bzoj 3669: [Noi2014]魔法森林
- BZOJ 3669 NOI2014 魔法森林 SPFA
- BZOJ 3669 [Noi2014]魔法森林 LCT
- 【LCT】BZOJ 3669: [Noi2014]魔法森林
- bzoj 3669 NOI2014 魔法森林 [LCT]
- [BZOJ 3669][Noi2014]魔法森林:SPFA
- BZOJ 3669 [Noi2014]魔法森林 LCT
- BZOJ 3669: [Noi2014]魔法森林 LCT
- BZOJ 3669 [Noi2014]魔法森林 Kruskal+LCT
- [BZOJ]3669: [Noi2014]魔法森林 lct
- BZOJ 3669 . JZOJ 3754. 【NOI2014】魔法森林
- 3669: [Noi2014]魔法森林
- 3669: [Noi2014]魔法森林
- 物理内存与虚拟内存解析
- echart图表控件配置入门(常用图表数据动态绑定)
- Spring文档
- 谁是世界上最丑的人
- .section 段
- bzoj 3669: [Noi2014]魔法森林
- java 内部类
- RFS自动化测试工具安装与使用总结
- Django学习笔记 --1 Hello world!
- bzoj4997: [Usaco2017 Feb]Why Did the Cow Cross the Road III
- MySQL技术问答-下篇
- pat 乙级 1012. 数字分类 (20)
- 阿里部分面试题整理
- Learning Scrapy 1