[NOI2014]魔法森林|动态树
2016-01-08 07:20
211 查看
此题spfa就能A 据说当年sd就有一位神犇用spfa在赛场上强势A了这道题
然而正解貌似是动态树维护生成树
先按a把边排序从小到大枚举插入新边
如果构成环那么把环上的最大的b值的边删掉
------------------------------------------------------
代码异常sb
然而正解貌似是动态树维护生成树
先按a把边排序从小到大枚举插入新边
如果构成环那么把环上的最大的b值的边删掉
------------------------------------------------------
代码异常sb
#include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<queue> #include<set> #include<map> #include<vector> #include<algorithm> #include<iostream> #define MX 123456789 using namespace std; int sc() { int i=0; char c=getchar(); while(c>'9'||c<'0') c=getchar(); while(c>='0'&&c<='9') i=i*10+c-'0',c=getchar(); return i; } struct E{int x,y,a,b;} e[111111]; bool rev[155555]; int ch[155555][2],fa[155555],mx[155555],val[155555],st[155555]; int p[155555]; int n,m,ans=MX; bool operator<(E a,E b){return a.a<b.a;} bool Root(int x){ return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; } int find(int x){return x==p[x]?x:p[x]=find(p[x]);} void push_down(int x) { if(rev[x]) { rev[x]^=1; rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; swap(ch[x][1],ch[x][0]); } } void push_up(int x) { int l=ch[x][0],r=ch[x][1]; mx[x]=x; if(val[mx[l]]>val[mx[x]])mx[x]=mx[l]; if(val[mx[r]]>val[mx[x]])mx[x]=mx[r]; } void rotate(int x) { int y=fa[x],z=fa[y],l,r; if(ch[y][0]==x) l=0; else l=1; r=l^1; if(!Root(y)) { if(ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; } fa[x]=z; fa[y]=x; fa[ch[x][r]]=y; ch[y][l]=ch[x][r]; ch[x][r]=y; push_up(y); push_up(x); } void splay(int x) { int top=0; st[++top]=x; for(int i=x;!Root(i);i=fa[i]) st[++top]=fa[i]; while(top)push_down(st[top--]); while(!Root(x)) { int y=fa[x],z=fa[y]; if(!Root(y)) { if(ch[z][0]==y^ch[y][0]==x) rotate(y); else rotate(x); } rotate(x); } } void access(int x) { for(int t=0;x;t=x,x=fa[x]) splay(x),ch[x][1]=t,push_up(x); } void make_root(int x){access(x),splay(x),rev[x]=1;} void link(int x,int y){make_root(x),fa[x]=y;} void cut(int x,int y){make_root(x),access(y),splay(y),ch[y][0]=fa[x]=0,push_up(y);} int query(int x,int y) { make_root(x),access(y),splay(y); return mx[y]; } int main() { n=sc(),m=sc(); for(int i=1;i<=n;i++)p[i]=i; for(int i=1;i<=m;i++) e[i].x=sc(),e[i].y=sc(),e[i].a=sc(),e[i].b=sc(); sort(e+1,e+m+1); for(int i=1;i<=m;i++) { int x=e[i].x,y=e[i].y,a=e[i].a,b=e[i].b; if(find(x)==find(y)) { int t=query(x,y); if(val[t]>e[i].b) cut(t,e[t-n].x),cut(t,e[t-n].y); else { if(find(1)==find(n)) ans=min(ans,a+val[query(1,n)]); continue; } } else p[find(x)]=find(y); val[n+i]=b; mx[n+i]=n+i; link(x,n+i),link(y,n+i); if(find(1)==find(n)) ans=min(ans,a+val[query(1,n)]); } if(ans==MX) puts("-1"); else cout<<ans; return 0; }
相关文章推荐
- python学习之socket创建html服务器
- 01课程介绍-DirectX游戏开发初级教程
- [leetcode] 61. Rotate List 解题报告
- LNMP一键安装包
- PHP的单态类——为了产生唯一的对象
- Docker实战(十一):Docker安装ELK环境(二)
- 经纬度转换成屏幕坐标
- 《软件需求》读书笔记3
- 《软件需求》读书笔记2
- 《软件需求》读书笔记1
- ios之"performSelector may cause a leak because its selector is unknown"警告原因及其解决办法
- Android笔记(七十四) 详解Intent
- *Reverse Words in a String II
- java:读写csv文件
- Android开发之常用Intent.Action【转】
- Object_c底层细节
- 网络编程的概述
- java:学期projet总结,大图可视化
- 跟我学习dubbo-在Linux操作系统上手工部署Dubbo服务(5)
- 跟我学习dubbo-在Linux操作系统上手工部署Dubbo服务(5)