bzoj3669 魔法森林(NOI 2014)
来源:互联网 发布:pkpm建筑设计软件 编辑:程序博客网 时间:2024/05/29 12:43
对于每条边,新建一个点连向2个端点。。。。再排序加边
/************************************************************** Problem: 3669 User: Clare Language: C++ Result: Accepted Time:4740 ms Memory:9284 kb****************************************************************/ #include <cstdio>#include <iostream>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <queue>#include <vector>using namespace std; #define N 200010#define INF 0x7fffffff int n,m,Ans;int size[N],fa[N],c[N][2],Max[N],v[N];struct Node{ int u,v,a,b; bool operator < (const Node &t) const{ return a==t.a?b<t.b:a<t.a; }}A[N];bool Rev[N];stack<int> st; inline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return x*f;} bool Pd_root(int k){ return !(c[fa[k]][0]==k)&&!(c[fa[k]][1]==k);} void Pushup(int k){ int l=c[k][0],r=c[k][1]; Max[k]=k; if(v[Max[k]]<v[Max[l]])Max[k]=Max[l]; if(v[Max[k]]<v[Max[r]])Max[k]=Max[r];} void Pushdown(int k){ int l=c[k][0],r=c[k][1]; if(Rev[k]) { Rev[k]^=1;Rev[r]^=1;Rev[l]^=1; swap(c[k][0],c[k][1]); }} void Rotate(int x){ int y=fa[x],z=fa[y],l,r; if(c[y][0]==x)l=0;else l=1;r=l^1; if(Pd_root(y)); else if(c[z][0]==y)c[z][0]=x; else c[z][1]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; Pushup(y);Pushup(x);} void Splay(int x){ int i; for(i=x;!Pd_root(i);i=fa[i]) st.push(i); st.push(i); while(!st.empty()) { int now=st.top();st.pop(); Pushdown(now); } while(!Pd_root(x)) { int y=fa[x],z=fa[y]; if(!Pd_root(y)) { if(c[y][0]==x^c[z][0]==y) Rotate(x); else Rotate(y); } Rotate(x); }} void Access(int x){ for(int t=0;x;t=x,x=fa[x]) Splay(x),c[x][1]=t,Pushup(x);} void Move_to_root(int x){ Access(x);Splay(x);Rev[x]^=1;} void Join(int x,int y){ Move_to_root(x);fa[x]=y;Splay(x);} void Cut(int x,int y){ Move_to_root(x);Access(y);Splay(y); if(c[y][0]==x) fa[x]=c[y][0]=0; else fa[x]=c[y][1]=0; Pushup(y);Pushup(x);} void Split(int x,int y){ Move_to_root(x);Access(y);Splay(y);} int Find_root(int x){ Access(x);Splay(x); while(c[x][0]) x=c[x][0]; return x;} int main(){ n=read();m=read();Ans=INF; for(int i=1;i<=n;i++) Max[i]=i; for(int i=1;i<=m;i++) { A[i].u=read();A[i].v=read();A[i].a=read();A[i].b=read(); } sort(A+1,A+m+1); for(int i=1;i<=m;i++) { if(Find_root(A[i].u)==Find_root(A[i].v)) { Split(A[i].u,A[i].v); int t=Max[A[i].v]; if(v[t]>A[i].b) { Cut(t,A[t-n].u);Cut(t,A[t-n].v); v[n+i]=A[i].b;Max[n+i]=n+i; Join(n+i,A[i].u);Join(n+i,A[i].v); if(Find_root(1)==Find_root(n)) { Split(1,n); Ans=min(Ans,A[i].a+v[Max[n]]); } } else continue; } else { v[n+i]=A[i].b;Max[n+i]=n+i; Join(n+i,A[i].u);Join(n+i,A[i].v); if(Find_root(1)==Find_root(n)) { Split(1,n); Ans=min(Ans,A[i].a+v[Max[n]]); } } } if(Ans==INF) cout<<"-1"<<endl; else cout<<Ans<<endl; return 0;}
0 0
- bzoj3669 魔法森林(NOI 2014)
- NOI 2014魔法森林
- [NOI 2014]魔法森林
- BZOJ3669 [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- [BZOJ3669][Noi2014]魔法森林
- 【NOI2014】【BZOJ3669】魔法森林
- [bzoj3669][NOI2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669: [Noi2014]魔法森林
- BZOJ3669: [Noi2014]魔法森林
- bzoj3669 [Noi2014]魔法森林
- [BZOJ3669]魔法森林
- 【NOI2014】bzoj3669 魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- 【bzoj3669】[Noi2014]魔法森林
- BZOJ3669 [Noi2014]魔法森林
- cout输出字符串地址 http://cache.baiducontent.com/c?m=9f65cb4a8c8507ed4fece7631049c0666e04de3e69c0d0622e95
- Android 对话框(Dialog)【大全】
- android分析windowManager、window、viewGroup之间关系
- 建造者模式
- 从今天开始
- bzoj3669 魔法森林(NOI 2014)
- What are some of the differences between using recursion to solve a problem versus using iteration?
- java volatile double、long的原子性
- 平均一个集合为几个集合
- #DOM操作
- php历史版本页面
- 在C#应用中使用Matlab函数
- tar加减号时的作用 tar cf - | tar xf - 管道 linux
- Android 开发 调用图库选择图片实现和参数详解