zoukankan      html  css  js  c++  java
  • bzoj3051: [wc2013]平面图

    Description

    Input

    Output

    扫描线求出平面图的对偶图然后求最小生成树,用并查集按秩合并,以便查询两点间路径最大权

    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #include<set>
    #include<cmath>
    int f[200007],f2[200007],h2[200007];
    int get(int*f,int x){
        int a=x,c;
        while(x!=f[x])x=f[x];
        while(x!=f[a])c=f[a],f[a]=x,a=c;
        return x;
    }
    int get2(int x){
        while(x!=f2[x])x=f2[x];
        return x;
    }
    void merge(int a,int b){
        a=get(f,a);b=get(f,b);
        if(a<b)f[b]=a;
        else f[a]=b;
    }
    double X;
    struct ln{
        double k,b;int id;
        double operator()(double x)const{return k*x+b;}
        bool operator<(ln w)const{return operator()(X)+1e-8<w(X);}
    };
    std::set<ln>line;
    struct pos{
        double x,y;
        void R(){
            scanf("%lf%lf",&x,&y);
        }
    }ps[100007],qs[100007][2];
    struct dir{
        double d;
        int i1,i2;
        bool operator<(dir w)const{return d<w.d;}
    };
    std::vector<dir>vs[100007];
    struct ev{
        int t;
        double x;
        int w;
        bool operator<(ev a)const{return x!=a.x?x<a.x:t<a.t;}
    }e[500007];
    int ep=0,ee[200007];
    int n,m,q;
    struct edge{
        int a,b,c,ID;
        ln l;
        void R(int I){
            ID=I;
            scanf("%d%d%d",&a,&b,&c);
            if(ps[a].x>ps[b].x)std::swap(a,b);
            if(ps[a].x!=ps[b].x){
                e[ep++]=(ev){1,ps[a].x,I};
                e[ep++]=(ev){0,ps[b].x,I};
                double k=(ps[b].y-ps[a].y)/(ps[b].x-ps[a].x);
                l=(ln){k,ps[a].y-ps[a].x*k,I};
            }
            vs[a].push_back((dir){atan2(ps[b].y-ps[a].y,ps[b].x-ps[a].x),I,I+m});
            vs[b].push_back((dir){atan2(ps[a].y-ps[b].y,ps[a].x-ps[b].x),I+m,I});
        }
        bool operator<(const edge&w)const{return c<w.c;}
    }es[100007];
    int ws[100007][2];
    void maxs(int&a,int b){if(a<b)a=b;}
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m*2;++i)f[i]=f2[i]=i;
        for(int i=1;i<=n;++i)ps[i].R();
        for(int i=1;i<=m;++i)es[i].R(i);
        scanf("%d",&q);
        for(int i=1;i<=q;++i){
            qs[i][0].R();
            qs[i][1].R();
            e[ep++]=(ev){2,qs[i][0].x,i};
            e[ep++]=(ev){3,qs[i][1].x,i};
        }
        std::sort(e,e+ep);
        e[ep].x=e[ep-1].x+10000;
        double x0=e[0].x-10000,x1;
        for(int i=0,j=0;i<ep;){
            x1=e[i].x;
            for(;j<ep&&e[j].x==x1;++j);
            X=(x0+x1)/2.;
            for(;i<j&&e[i].t==0;++i){
                std::set<ln>::iterator it=line.find(es[e[i].w].l);
                line.erase(it);
            }
            X=(x1+e[j].x)/2.;
            for(int k=i;k<j&&e[k].t==1;++k){
                ln w=es[e[k].w].l;
                line.insert(w);
            }
            for(;i<j&&e[i].t==1;++i){
                ln w=es[e[i].w].l;
                std::set<ln>::iterator it=line.find(w);
                ++it;
                if(it==line.end())merge(0,e[i].w+m);
                else merge(e[i].w+m,it->id);
                --it;
                if(it==line.begin())merge(0,e[i].w);
                else --it,merge(e[i].w,it->id+m);
            }
            X=x1;
            for(;i<j;++i){
                ln w=(ln){0,qs[e[i].w][e[i].t-2].y,0};
                std::set<ln>::iterator it=line.lower_bound(w);
                if(it!=line.end())ws[e[i].w][e[i].t-2]=it->id;
            }
            x0=x1;
        }
        for(int i=1;i<=n;++i)if(!vs[i].empty()){
            std::sort(vs[i].begin(),vs[i].end());
            vs[i].push_back(vs[i][0]);
            for(int j=1;j<vs[i].size();++j){
                merge(vs[i][j-1].i2,vs[i][j].i1);
            }
        }
        std::sort(es+1,es+m+1);
        for(int i=1;i<=m;++i){
            int x=get2(get(f,es[i].ID));
            int y=get2(get(f,es[i].ID+m));
            if(x&&y&&x!=y){
                if(h2[x]<h2[y])f2[x]=y,ee[x]=es[i].c;
                else{
                    if(h2[x]==h2[y])++h2[x];
                    f2[y]=x;ee[y]=es[i].c;
                }
            }
        }
        for(int i=1;i<=q;++i){
            int x=get(f,ws[i][0]),y=get(f,ws[i][1]);
            if(!x||!y)puts("-1");
            else{
                int v=0;
                while(x!=y){
                    if(h2[x]>h2[y])std::swap(x,y);
                    maxs(v,ee[x]);
                    x=f2[x];
                }
                printf("%d
    ",v);
            }
        }
        return 0;
    }
  • 相关阅读:
    页面跳转时,统计数据丢失问题探讨
    JSBridge 知识点
    数据埋点 知识点
    ES6 模块与 CommonJS 模块的差异
    koa 学习资料
    浏览器渲染流程
    Object.create() 的含义:从一个实例对象,生成另一个实例对象
    this、new,容易混淆的地方
    为什么js 的constructor中是无限循环嵌套:Foo.__proto__.constructor.prototype.constructor.prototype.constructor.prototype.xxx ?
    实例对象与 new 命令
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6254198.html
Copyright © 2011-2022 走看看