bzoj 3669

Posted zhangleo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3669相关的知识,希望对你有一定的参考价值。

思想基本同bzoj 2594,但是多了一步

首先我们发现这时的边有两个属性了,因此我们考虑先去掉其中一者的限制

我们把所有边按$a$大小排序,然后从小到大加入维护的最小生成树

每次加边时都按照$b$的大小操作bzoj 2594,然后更新答案即可

如果始终不联通输出-1

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
using namespace std;
struct Ques

    int x,y,typ,num;
q[1000005];
struct Edge

    int l,r,v1,v2;
    friend bool operator < (Edge a,Edge b)
    
        return a.v1==b.v1?a.v2<b.v2:a.v1<b.v1;
    
edge[1000005];
map <pair<int,int>,int> M;
int n,m,Q;
int ch[2000005][2];
int vis[2000005];
int maxx[2000005];
int val[2000005];
int f[2000005];
int fl[2000005];
int ret[2000005];
void update(int x)

    maxx[x]=val[x];
    if(edge[maxx[ch[x][0]]].v2>edge[maxx[x]].v2)maxx[x]=maxx[ch[x][0]];
    if(edge[maxx[ch[x][1]]].v2>edge[maxx[x]].v2)maxx[x]=maxx[ch[x][1]];

bool be_root(int x)

    if(ch[f[x]][0]==x||ch[f[x]][1]==x)return 0;
    return 1;

void pushdown(int x)

    if(fl[x])
    
        swap(ch[ch[x][0]][0],ch[ch[x][0]][1]);
        swap(ch[ch[x][1]][0],ch[ch[x][1]][1]);
        fl[ch[x][0]]^=1,fl[ch[x][1]]^=1;
        fl[x]=0;
    

void repush(int x)

    if(!be_root(x))repush(f[x]);
    pushdown(x);

void rotate(int x)

   int y=f[x],z=f[y],k=(ch[y][1]==x);
    if(!be_root(y))ch[z][ch[z][1]==y]=x;
    f[x]=z;
    ch[y][k]=ch[x][!k],f[ch[x][!k]]=y;
    ch[x][!k]=y,f[y]=x;
    update(y),update(x);

void splay(int x)

    repush(x);
    while(!be_root(x)&&x)
    
        int y=f[x],z=f[y];
        if(!be_root(y)&&y)
        
            if((ch[y][1]==x)^(ch[z][1]==y))rotate(x);
            else rotate(y);
        
        rotate(x);
    
    update(x);

void access(int x)

    int y=0;
    while(x)
    
        splay(x);
        ch[x][1]=y;
        update(x);
        y=x,x=f[x];
    

void makeroot(int x)

    access(x),splay(x);
    swap(ch[x][0],ch[x][1]),fl[x]^=1;

void link(int x,int y)

    makeroot(x);
    f[x]=y;

void split(int x,int y)

    makeroot(x),access(y),splay(y);

void cut(int x,int y)

    split(x,y),ch[y][0]=f[x]=0,update(y);

int findf(int x)

    access(x),splay(x),pushdown(x);
    while(ch[x][0])x=ch[x][0],pushdown(x);
    return x;

inline int read()

    int f=1,x=0;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++)
    
        edge[i].l=read(),edge[i].r=read(),edge[i].v1=read(),edge[i].v2=read();
        if(edge[i].l>edge[i].r)swap(edge[i].l,edge[i].r);
    
    sort(edge+1,edge+m+1);
    int ans=0x3f3f3f3f;
    for(int i=1;i<=m;i++)val[i+n]=maxx[i+n]=i;
    for(int i=1;i<=m;i++)
    
        int f1=findf(edge[i].l),f2=findf(edge[i].r);
        if(f1==f2)
        
            split(edge[i].l,edge[i].r);
            if(edge[maxx[edge[i].r]].v2>edge[i].v2)
            
                int t=maxx[edge[i].r];
                cut(edge[t].l,t+n),cut(edge[t].r,t+n);
                link(edge[i].l,i+n),link(edge[i].r,i+n);
            
        else link(edge[i].l,i+n),link(edge[i].r,i+n);
        int ff1=findf(1),ff2=findf(n);
        if(ff1==ff2)
        
            split(1,n);
            ans=min(ans,edge[i].v1+edge[maxx[n]].v2);
        
    
    if(ans==0x3f3f3f3f)printf("-1\\n");
    else printf("%d\\n",ans);
    return 0;

 

以上是关于bzoj 3669的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3669[Noi2014]魔法森林

BZOJ 3669: [Noi2014]魔法森林( LCT )

bzoj3669: [Noi2014]魔法森林

BZOJ3669: [Noi2014]魔法森林

BZOJ3669: [Noi2014]魔法森林

[BZOJ3669][Noi2014]魔法森林