ccz181078

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

Description

给定一个凸n边形,以及它的三角剖分。再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b。

Input

 第一行一个整数n(n <= 50000),代表有n个点。点1,2,3,…,n是凸多边形上是顺时针排布的。

接下来n-3行,每行两个整数(x,y),代表(x,y)之间有一条剖分边。
接下来是一个整数q(q <= 100000),代表有q组询问。
接下来q行是两个整数(a,b)。

Output

输出q行,每行一个整数代表最少边数。
类似边分治,每次选一条边将多边形分为两部分,处理经过边的端点的路线,递归分治
#include<bits/stdc++.h>
char buf[70007],*ptr=buf+70000;
int G(){
    if(ptr-buf==70000)fread(ptr=buf,1,70000,stdin);
    return *ptr++;
}
int _(){
    int x=0;
    if(ptr-buf<69900){
        while(*ptr<48)++ptr;
        while(*ptr>47)x=x*10+*ptr++-48;
    }else{
        int c=G();
        while(c<48)c=G();
        while(c>47)x=x*10+c-48,c=G();
    }
    return x;
}
const int N=100007,inf=0x3f3f3f3f,P=293999;
int n,qp,idp=0;
int deg[N],q[N],ql=0,qr=0,as[N];
std::vector<int>e0[N],ee[N];
struct Q{int w,id;};
std::vector<Q>qq[N];
Q*qs[N][2];
int sz[N],*lr[N][2],*et[N][2];
int p3[N][3];
void ae(int a,int b){
    ++deg[b];++deg[a];
    e0[a].push_back(b);
    e0[b].push_back(a);
}

struct hash_map{
    int h[P][4];
    int*operator()(int a,int b){
        if(a>b)std::swap(a,b);
        int w=(a*1399+b*293)%P;
        while(h[w][0]){
            if(h[w][0]==a&&h[w][1]==b)return h[w]+2;
            if((w+=1237)>=P)w-=P;
        }
        h[w][0]=a,h[w][1]=b;
        return h[w]+2;
    }
}h1,h2;
void chk(int a,int b){
    if(a>b)std::swap(a,b);
    if(a==1&&b==n||a+1==b)return;
    int*w=h1(a,b);
    if(w[0]){
        int x=idp,y=w[0];
        ee[x].push_back(y);
        ee[y].push_back(x);
        int*c=h2(x,y);
        c[0]=a;c[1]=b;
    }else w[0]=idp;
}
int ss[N][2],sp,tk=1,ed[N],ed2[N];
int ps[N],pp=0;
void ins(int a){
    for(int t=0;t<3;++t){
        int w=p3[a][t];
        if(ed2[w]!=tk)ed2[ps[pp++]=w]=tk;
    }
}
void f2(int w,int pa){
    sz[w]=1;
    ed[w]=tk;
    ss[sp][0]=w,ss[sp++][1]=pa;
    for(int*l=lr[w][0],*r=lr[w][1];l!=r;++l){
        int u=*l;
        if(u==pa)continue;
        f2(u,w);
        sz[w]+=sz[u];
    }
}
void dele(int a,int b){
    for(int*l=lr[a][0],*r=lr[a][1];l!=r;++l)if(*l==b){
        *l=*--lr[a][1];
        return;
    }
}
int min(int a,int b){return a<b?a:b;}
void mins(int&a,int b){if(a>b)a=b;}
int d1[N],d2[N],dd1[N],dd2[N],dk=1;
bool qd[N];
void bfs(int w,int*d,int*dd){
    ql=qr=0;
    dd[q[++qr]=w]=dk,d[w]=0;
    while(ql!=qr){
        w=q[++ql];
        for(int*l=et[w][0],*r=et[w][1];l!=r;++l){
            int u=*l;
            if(ed2[u]==tk&&dd[u]!=dk)dd[q[++qr]=u]=dk,d[u]=d[w]+1;
        }
    }
}
void f1(int w){
    ++tk;
    pp=0;
    sp=0;
    f2(w,0);
    int SZ=sz[w];
    if(SZ>1){
        int mx=0,p1=w,p2=0;
        for(int i=0;i<sp;++i){
            int u=ss[i][0],mv=min(sz[u],SZ-sz[u]);
            if(mv>mx)mx=mv,p1=u,p2=ss[i][1];
            ins(u);
        }
        dele(p1,p2);
        dele(p2,p1);
        int*ns=h2(p1,p2);
        ++dk;
        bfs(ns[0],d1,dd1);bfs(ns[1],d2,dd2);
        for(int i=0;i<pp;++i){
            int u=ps[i];
            int d1u=d1[u];
            int d2u=d2[u];
            for(Q*l=qs[u][0],*r=qs[u][1];l!=r;++l){
                int v=l->w;
                if(qd[v])*l--=*(qs[u][1]=--r);
                else if(ed2[v]==tk){
                    int d1v=d1[v];
                    int d2v=d2[v];
                    mins(as[l->id],min(min(d1u+d1v,d2u+d2v),min(d1u+d2v+1,d2u+d1v+1)));
                }
            }
        }
        qd[ns[0]]=qd[ns[1]]=1;
        for(int d=0;d<2;++d)qs[ns[d]][0]=qs[ns[d]][1];
        f1(p1);f1(p2);
    }
}
int main(){
    n=_();
    for(int i=1,a,b;i<=n-3;++i){
        a=_();b=_();
        ae(a,b);
    }
    for(int i=1;i<=n;++i)ae(i,i==n?1:i+1);
    for(int i=1;i<=n;++i){
        et[i][0]=e0[i].data();
        et[i][1]=et[i][0]+e0[i].size();
    }
    for(int i=1;i<=n;++i)if(deg[i]==2)q[++qr]=i;
    while(ql!=qr){
        int w=q[++ql];
        if(deg[w]!=2)break;
        deg[w]=0;
        int cs[3],cp=0;
        cs[cp++]=w;
        for(int*l=et[w][0],*r=et[w][1];l!=r;++l){
            int u=*l;
            if(!deg[u])continue;
            cs[cp++]=u;
            if(2==--deg[u])q[++qr]=u;
        }
        ++idp;
        for(int i=0;i<3;++i){
            for(int j=0;j<i;++j)chk(cs[i],cs[j]);
            p3[idp][i]=cs[i];
        }
    }
    for(int i=1;i<=idp;++i){
        lr[i][0]=ee[i].data();
        lr[i][1]=lr[i][0]+ee[i].size();
    }
    qp=_();
    for(int i=0;i<qp;++i){
        int x=_(),y=_();
        if(x==y)continue;
        if(x>y)std::swap(x,y);
        if(x==1&&y==n||x+1==y||h1(x,y)[0]){
            as[i]=1;
            continue;
        }
        as[i]=inf;
        qq[x].push_back((Q){y,i});
        qq[y].push_back((Q){x,i});
    }
    for(int i=1;i<=idp;++i){
        qs[i][0]=qq[i].data();
        qs[i][1]=qs[i][0]+qq[i].size();
    }
    f1(1);
    for(int i=0;i<qp;++i)printf("%d\n",as[i]);
    return 0;
}

 

posted on 2017-07-05 18:15  nul  阅读(330)  评论(0编辑  收藏  举报