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
原创粉丝点击