• bzoj1760 [Baltic2009]Triangulation


    给定一个多边形的三角剖分(n<=1e5),且每个三角形有其颜色,问最多可以把这个三角剖分分成几个联通的部分,使任何一种颜色不出现在多个连通块中

    建出三角剖分对应的树,同种颜色的点之间的路径是不能被切开的,因此将同色的点间路径标记一下,未标记的边数即为答案

    具体实现可以用树上差分进行标记,树链剖分lca,同色的点按dfs序排序并将排序后相邻的点间路径标记

    #include<cstdio>
    #include<algorithm>
    typedef long long i64;
    const int R=5e6,N=100007,P=1844677;
    char buf[R],*ptr=buf-1;
    int _(){
        int x=0,c=*++ptr;
        while(c<48)c=*++ptr;
        while(c>47)x=x*10+c-48,c=*++ptr;
        return x;
    }
    long long hx[P];
    int hy[P];
    int n,ans=-1;
    int e[N][3],ep[N],col[N],cc[N],*cl[N],*cr[N],_c[N],*cp=_c,v[N];
    int fa[N],sz[N],son[N],dep[N],top[N],id[N],idp=0;
    void chk(int a,int b,int id){
        if(a>b)std::swap(a,b);
        i64 h=i64(a)<<20|b;
        int w=h%P;
        while(hy[w]){
            if(hx[w]==h){
                e[hy[w]][ep[hy[w]]++]=id;
                e[id][ep[id]++]=hy[w];
                return;
            }
            if((w+=12347)>=P)w-=P;
        }
        hx[w]=h;hy[w]=id;
    }
    void f1(int w,int pa){
        fa[w]=pa;
        dep[w]=dep[pa]+1;
        sz[w]=1;
        for(int i=0;i<ep[w];++i){
            int u=e[w][i];
            if(u==pa)continue;
            f1(u,w);
            sz[w]+=sz[u];
            if(sz[son[w]]<sz[u])son[w]=u;
        }
    }
    void f2(int w,int tp){
        top[w]=tp;
        id[w]=++idp;
        if(son[w])f2(son[w],tp);
        for(int i=0;i<ep[w];++i){
            int u=e[w][i];
            if(u==fa[w]||u==son[w])continue;
            f2(u,u);
        }
    }
    void f3(int w){
        for(int i=0;i<ep[w];++i){
            int u=e[w][i];
            if(u==fa[w])continue;
            f3(u);
            v[w]+=v[u];
        }
        if(!v[w])++ans;
    }
    int lca(int x,int y){
        int a=top[x],b=top[y];
        while(a!=b){
            if(dep[a]<dep[b])std::swap(a,b),std::swap(x,y);
            x=fa[a];a=top[x];
        }
        return dep[x]<dep[y]?x:y;
    }
    bool cmp(int a,int b){
        return id[a]<id[b];
    }
    int main(){
        fread(buf,1,R,stdin);
        n=_()-2;
        for(int i=1;i<=n;++i){
            int a=_(),b=_(),c=_();
            chk(a,b,i);
            chk(a,c,i);
            chk(c,b,i);
            ++cc[col[i]=_()];
        }
        for(int i=1;i<=n;++i)cl[i]=cr[i]=cp,cp+=cc[i];
        for(int i=1;i<=n;++i)*(cr[col[i]]++)=i;
        f1(1,0);
        f2(1,1);
        for(int i=1;i<=n;++i)if(cl[i]!=cr[i]){
            std::sort(cl[i],cr[i],cmp);
            for(int p=1;p<cc[i];++p){
                int x=cl[i][p],y=cl[i][p-1],z=lca(x,y);
                ++v[x];++v[y];v[z]-=2;
            }
        }
        f3(1);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    WikiPedia技术架构学习笔记
    MySQL 架构设计篇 (十二) 可扩展设计的基本原则
    php前端控制器二
    php前端控制器三
    构建可扩展的WEB站点读书笔记
    发布脚本开发框架代码
    改良dbgrideh的文字过滤
    cxgrid在当前View插入记录
    生成不重复单据编号
    cxgrid按条件计算合计值
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6067629.html
Copyright © 2020-2023  润新知