ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

给定一个多边形的三角剖分(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;
}

 

posted on 2016-11-15 22:38  nul  阅读(231)  评论(0编辑  收藏  举报