首页 > 代码库 > bzoj1760 [Baltic2009]Triangulation

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;}

 

bzoj1760 [Baltic2009]Triangulation