[NOI2014][JZOJ3754][BZOJ3669]魔法森林
来源:互联网 发布:云计算的部署方式 编辑:程序博客网 时间:2024/05/20 10:13
题目大意
给定一个
你需要找到一条从
题目分析
这题看上去就很mst套路,实际上也是mst套路。
考虑从小到大枚举路径上
如果形成了环就删掉环上
使用LCT维护森林,使用并查集维护连通性。
时间复杂度
代码实现
人生第一发lct居然很快就调过了,exciting!
#include <algorithm>#include <iostream>#include <cstdio>#include <cctype>#include <stack>using namespace std;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}const int INF=1000000000;const int N=50005;const int M=100005;const int V=N+M;struct edge{ int x,y,a,b; bool operator<(edge const ed)const{return a<ed.a;} void load(){x=read(),y=read(),a=read(),b=read();}}edg[M];int fa[N],rank[N];int n,m,ans;struct link_cut_tree{ int par[V],fa[V],size[V],id[V],mx[V]; int son[V][2]; stack<int> st; bool mark[V]; bool side(int x){return son[fa[x]][1]==x;} void R(int x){swap(son[x][0],son[x][1]),mark[x]^=1;} void clear(int x) { if (mark[x]) { if (son[x][0]) R(son[x][0]); if (son[x][1]) R(son[x][1]); mark[x]=0; } } void update(int x) { size[x]=size[son[x][0]]+size[son[x][1]]+1; mx[x]=edg[mx[son[x][0]]].b>edg[mx[son[x][1]]].b?mx[son[x][0]]:mx[son[x][1]]; mx[x]=edg[id[x]].b>edg[mx[x]].b?id[x]:mx[x]; } void pushdown(int x,int y) { for (;x!=y;st.push(x),x=fa[x]); for (;!st.empty();clear(st.top()),st.pop()); } void rotate(int x) { int y=fa[x];bool s=side(x); if (fa[y]) son[fa[y]][side(y)]=x; if (son[x][s^1]) fa[son[x][s^1]]=y; son[y][s]=son[x][s^1],son[x][s^1]=y; fa[x]=fa[y],fa[y]=x; if (par[y]) par[x]=par[y],par[y]=0; update(y),update(x); } void splay(int x,int y) { for (pushdown(x,y);fa[x]!=y;rotate(x)) if (fa[fa[x]]!=y) if (side(x)==side(fa[x])) rotate(fa[x]); else rotate(x); } int access(int x) { int nxt=0; for (;x;update(nxt=x),x=par[x]) { splay(x,0); if (son[x][1]) fa[son[x][1]]=0,par[son[x][1]]=x; son[x][1]=nxt; if (nxt) fa[nxt]=x,par[nxt]=0; } return nxt; } void makeroot(int x){R(access(x));} void link(int x,int y) { makeroot(x),access(x),splay(x,0); par[x]=y,access(x); } void cut(int x,int y) { makeroot(x),access(y),splay(y,0); fa[x]=son[y][0]=0,par[y]=0,update(y); } int query(int x,int y) { makeroot(x),access(y),splay(y,0); return mx[y]; }}lct;int getfather(int son){return fa[son]==son?son:fa[son]=getfather(fa[son]);}void merge(int x,int y){ if (rank[x]>rank[y]) swap(x,y); fa[y]=x,rank[y]+=rank[x]==rank[y];}void calc(){ for (int i=1;i<=n;++i) fa[i]=i; sort(edg+1,edg+1+m),ans=INF; for (int i=1;i<=n+m;++i) lct.size[i]=1; for (int i=1;i<=m;++i) { int x=edg[i].x,y=edg[i].y,fx=getfather(x),fy=getfather(y); if (fx!=fy) merge(fx,fy),lct.mx[i+n]=lct.id[i+n]=i,lct.link(x,i+n),lct.link(i+n,y); else { int id=lct.query(x,y); if (edg[id].b>edg[i].b) { int u=edg[id].x,v=edg[id].y; lct.cut(u,id+n),lct.cut(id+n,v); lct.mx[i+n]=lct.id[i+n]=i,lct.link(x,i+n),lct.link(i+n,y); } } if (getfather(1)==getfather(n)) ans=min(ans,edg[i].a+edg[lct.query(1,n)].b); }}int main(){ freopen("forest.in","r",stdin),freopen("forest.out","w",stdout); n=read(),m=read(); for (int i=1;i<=m;++i) edg[i].load(); calc(); if (ans==INF) printf("-1\n"); else printf("%d\n",ans); fclose(stdin),fclose(stdout); return 0;}
0 0
- [NOI2014][JZOJ3754][BZOJ3669]魔法森林
- [JZOJ3754]【NOI2014】魔法森林
- BZOJ3669 [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- [BZOJ3669][Noi2014]魔法森林
- 【NOI2014】【BZOJ3669】魔法森林
- [bzoj3669][NOI2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669 [Noi2014]魔法森林
- 【NOI2014】bzoj3669 魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- BZOJ3669 [Noi2014]魔法森林
- 【jzoj3754】【NOI2014】【魔法森林】【lct】
- bzoj3669: [Noi2014]魔法森林 LCT
- 安卓端获取IPV4和MAC地址
- C语言回炉(4)
- git commit/ git rebase /git pull/git reflog
- 搭建SQL的web环境
- Retrofit2.0学习之Post请求
- [NOI2014][JZOJ3754][BZOJ3669]魔法森林
- 前端开源项目周报0407
- 测试Or测试开发?
- MicroService 微服务架构模式简介
- POI
- ObjectBox初识与依赖配置
- IOC Unity
- 关于mysql数据库时间 和查询出来的时间不一致问题
- POJ3630 trie字典树水题