• bzoj2965: 保护古迹


    Description

      某校由于历史悠久,校园中有大量的名胜古迹。为了更好地保护这些古迹,学校决定用篱笆将这些古迹围起来。
      现在已知有p个地点的古迹需要保护。这些古迹可以看做二维平面上的整数点。有n个点可以作为篱笆的端点,这些端点的坐标也为二维平面上的整数。端点用1到n的整数编号。
      有m对端点之间可以修建篱笆。用(u,v,w)描述一段可以修建的篱笆,表示端点u和端点v之间可以花费w的代价修建一段。篱笆都看做直线段。为了方便设计,这些可以修建的篱笆都是不会相交的(只会在端点处相交)。
      将一个古迹围起来是指存在一个由篱笆构成的简单多边形,这个古迹在该多边形内部。
      由于经费问题,学校希望修建篱笆的花费最小。你需要输出将至少1个,2个,…,p个古迹围起来的最小花费。

    Input

      第一行包含三个正整数p,n,m表示古迹的个数,端点个数和可以修建的篱笆条数。
      接下来p行,每行包含两个整数,表示每个古迹的坐标。
      接下来n行,每行包含两个整数,表示每个端点的坐标。这些端点按照输入的顺序依次用1到n的整数编号。
      最后m行,每行包含三个非负整数u,v,w,表示可以在端点u和端点v之间花w的代价修建一段篱笆。

    Output

      输出p行,分别表示将至少1个,2个,…,p个古迹围起来的最小花费。

    扫描线做一下平面图转对偶图以及点定位,然后枚举选哪些点求最小割。
    #include<bits/stdc++.h>
    typedef long long i64;
    int p,n,m,f[30007],ep=0;
    int gf(int x){
        while(x!=f[x])x=f[x]=x[f][f];
        return x;
    }
    void mg(int a,int b){
        f[gf(a)]=gf(b);
    }
    struct pos{
        int x,y;
        void R(){scanf("%d%d",&x,&y);}
        pos operator+(pos w)const{return (pos){x+w.x,y+w.y};}
        pos operator-(pos w)const{return (pos){x-w.x,y-w.y};}
        i64 operator*(pos w)const{return i64(x)*w.y-i64(y)*w.x;}
    }ps[15];
    struct edge{
        int to,v;
        double a;
        pos p;
        int i1,i2;
        bool operator<(const edge&e)const{
            return fabs(a-e.a)<0.5?p*e.p>0:a<e.a;
        }
    };
    int min(int a,int b){return a<b?a:b;}
    int max(int a,int b){return a>b?a:b;}
    struct seg{
        pos p1,p2;
        int i1,i2;
        double at(double x)const{
            int d=p2.x-p1.x;
            return d?((x-p1.x)*p2.y+(p2.x-x)*p1.y)/d:p1.y;
        }
        bool operator<(const seg&w)const{
            double x1=(max(p1.x,w.p1.x)+min(p2.x,w.p2.x))*.5;
            return at(x1)<w.at(x1);
        }
    };
    struct event{
        int tp,x,id1,id2;
        bool operator<(const event&e)const{return x<e.x||x==e.x&&tp<e.tp;}
        void cal();
    }ev[50007];
    int evp=0;
    struct vertex{
        pos p;
        std::vector<edge>e;
        void R(){p.R();}
        void ae(int,int,int,int);
        void init();
        seg getseg(int w){
            return (seg){p,e[w].p+p,e[w].i1,e[w].i2};
        }
    }ns[111];
    void vertex::ae(int to,int v,int id1,int id2){
        pos d=ns[to].p-p;
        e.push_back((edge){to,v,atan2(d.y,d.x),d,id1,id2});
    }
    void vertex::init(){
        edge*es=e.data();
        int ec=e.size();
        if(ec){
            std::sort(es,es+ec);
            for(int i=1;i<ec;++i)mg(es[i-1].i2,es[i].i1);
            mg(es[ec-1].i2,es[0].i1);
            for(int i=0;i<ec;++i)if(es[i].p.x>0){
                ev[evp++]=(event){1,p.x,this-ns,i};
                ev[evp++]=(event){-1,p.x+es[i].p.x,this-ns,i};
            }
        }
    }
    std::set<seg>ln;
    std::set<seg>::iterator it,il,ir,its[50007];
    int itp=0;
    void event::cal(){
        if(tp==-1){
            seg s=ns[id1].getseg(id2);
            ln.erase(ln.find(s));
        }else if(tp==2){
            it=ln.lower_bound((seg){ps[id1],ps[id1]});
            mg(id1+1,it!=ln.end()?it->i1:0);
            mg(it!=ln.begin()?(--it)->i2:0,id1+1);
        }else{
            seg s=ns[id1].getseg(id2);
            its[itp++]=ln.insert(s).first;
        }
    }
    int id[50007],idp=0,ans[15];
    namespace mxf{
    const int N=300007,inf=0x3f3f3f3f;
    struct edge{
        int to,nx,v;
    }e[N];
    int e0[N],ep=2,h[N],q[N],S,T;
    void ae(int a,int b,int c,int c2){
        if(!a||!b||a==b||c+c2==0)return;
        e[ep]=(edge){b,e0[a],c};e0[a]=ep++;
        e[ep]=(edge){a,e0[b],c2};e0[b]=ep++;
    }
    int min(int a,int b){return a<b?a:b;}
    bool bfs(){
        for(int i=1;i<=idp;++i)h[i]=0;
        int ql=0,qr=0;
        h[q[++qr]=S]=1;
        while(ql!=qr){
            int w=q[++ql];
            if(w==T)return 1;
            for(int i=e0[w];i;i=e[i].nx)if(e[i].v){
                int u=e[i].to;
                if(!h[u])h[q[++qr]=u]=h[w]+1;
            }
        }
        return 0;
    }
    int dfs(int w,int f){
        if(w==T)return f;
        int c,used=0;
        for(int i=e0[w];i;i=e[i].nx)if(e[i].v){
            int u=e[i].to;
            if(h[u]!=h[w]+1)continue;
            c=dfs(u,min(e[i].v,f-used));
            e[i].v-=c,e[i^1].v+=c,used+=c;
            if(f==used)return f;
        }
        h[w]=0;
        return used;
    }
    void cal(int s){
        ep=2;
        S=idp+1;T=id[gf(0)];
        int c1=0;
        for(int i=1;i<=S;++i)e0[i]=0;
        for(int i=0;i<p;++i)if(s>>i&1){
            ++c1;
            ae(S,id[gf(i+1)],inf,0);
        }
        for(int i=1;i<=n;++i){
            for(int j=0;j<ns[i].e.size();++j){
                ::edge&e=ns[i].e[j];
                if(e.p.x>0||e.p.x==0&&e.p.y>0)ae(id[gf(e.i1)],id[gf(e.i2)],e.v,e.v);
            }
        }
        int f=0;
        while(bfs()){
            f+=dfs(S,inf);
            if(f>=ans[c1])return;
        }
        ans[c1]=f;
    }
    }
    int main(){
        scanf("%d%d%d",&p,&n,&m);
        for(int i=0;i<p;++i)ps[i].R(),ev[evp++]=(event){2,ps[i].x,i};
        for(int i=1;i<=n;++i)ns[i].R();
        ep=p;
        for(int i=0,a,b,c;i<m;++i){
            scanf("%d%d%d",&a,&b,&c);
            ep+=2;
            ns[a].ae(b,c,ep-1,ep);
            ns[b].ae(a,c,ep,ep-1);
        }
        for(int i=1;i<=ep;++i)f[i]=i;
        for(int i=1;i<=n;++i)ns[i].init();
        std::sort(ev,ev+evp);
        for(int i=0,j=0;i<evp;i=j){
            for(;j<evp&&ev[i].x==ev[j].x;ev[j++].cal());
            while(itp){
                il=ir=it=its[--itp];
                mg(it->i2,(++ir)!=ln.end()?ir->i1:0);
                mg(il!=ln.begin()?(--il)->i2:0,it->i1);
            }
        }
        for(int i=0;i<=ep;++i)if(f[i]==i)id[i]=++idp;
        for(int i=1;i<=n;++i){
            for(int j=0;j<ns[i].e.size();++j){
                edge&e=ns[i].e[j];
            }
        }
        for(int i=0;i<=p;++i)ans[i]=0x7fffffff;
        for(int S=1;S<(1<<p);++S)mxf::cal(S);
        for(int i=1;i<=p;++i)printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    mysql 数据列按照逗号转成行
    powder designer 转数据库
    oracle 写入txt
    ORACLE 11g dblink 配置升级
    oracle 11g dblink配置
    spring ,mybatis多数据源
    基于shamir门限的秘密分存
    SM4加解密
    PHP对数据库的简单操作
    php实现计算器
  • 原文地址:https://www.cnblogs.com/ccz181078/p/7526656.html
Copyright © 2020-2023  润新知