BJ 集训测试10 城市

http://www.elijahqi.win/archives/2783
圆上均匀分布n 个点 然后 在这n个点中连n-3条边 且这些边不相交 有q次询问每次询问两点间的最短距离

因为原图是平面图所以可以考虑转成对偶图 然后点分治

不想写对偶图&点分治可以考虑边分治

每次选择一条边 将这条边左右的边的数量尽量平均分布

因为这题比较特殊是在一个圆环上 所以考虑 我给所有点标号 然后枚举所有点的连得边检查这两个标号相差的距离取最小的那条边即可 然后每次针对这两个点bfs一下 如果询问的两个点分在边的两边 那么直接统计答案否则去两边分治

#include
#include
#include
#include
#define N 110000
#define inf 0x3f3f3f3f
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=gc();}
    while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=gc();
    return x*f;
}
vector<int> eg[N];
struct node{int x,y,id;};
int n,cnt,dis[N][2],id[N],start,ans[N];
bool flag[N*22][2];
inline void bfs1(int x,int ii){
    queue<int> q;q.push(x);dis[x][ii]=0;flag[id[x]][ii]=1;
    while(!q.empty()){
        int x=q.front();q.pop();
        for (int i=0;iint y=eg[x][i];
            if (!flag[id[y]][ii]&&id[y]<=cnt&&id[y]>=start) 
                dis[y][ii]=dis[x][ii]+1,flag[id[y]][ii]=1,q.push(y);
        }
    }
}
inline void solve(const vector<int> &g,const vector &q){
    if (!q.size()) return;
    if (g.size()<=3) {for (int i=0;i1;return;}
    start=cnt+1;int st,ed,mn=inf;
    for (int i=0;ifor (int owo=0;owoint x=g[owo];
        for (int i=0;iint y=eg[x][i];if (id[y]>cnt||id[y]continue;
            int x1=x,y1=y;if (id[x1]>id[y1]) swap(x1,y1);
            int mx=max(id[y1]-id[x1]+1,cnt-id[y1]+1+id[x1]-start+1);
            if (mx0);bfs1(ed,1);vector<int> g1,g2;vector q1,q2;
    for (int i=0;iint x=q[i].x,y=q[i].y,idx=q[i].id,blx,bly;
        if (id[x]>=id[st]&&id[x]<=id[ed]) blx=1;else blx=2;
        if (id[y]>=id[st]&&id[y]<=id[ed]) bly=1;else bly=2;
        if(blx==bly){if (blx==1) q1.push_back(q[i]);else
            q2.push_back(q[i]);continue;}
        ans[idx]=min(dis[x][0]+dis[y][0],dis[x][1]+dis[y][1]);
    }
    for (int i=id[st]-start;i<=id[ed]-start;++i) g1.push_back(g[i]);
    for (int i=0;i<=id[st]-start;++i) g2.push_back(g[i]);
    for (int i=id[ed]-start;iint main(){
    freopen("t2.in","r",stdin);
    n=read();vector<int> g;vector q;
    for (int i=1;i<=n-3;++i){
        int x=read(),y=read();
        eg[x].push_back(y);eg[y].push_back(x);
    }
    for (int i=0;i1;++i) eg[i].push_back(i+1),eg[i+1].push_back(i);
    eg[n-1].push_back(0);eg[0].push_back(n-1);int m=read();g.reserve(n);q.reserve(m);
    for (int i=0;ifor (int i=1;i<=m;++i){
        int x=read(),y=read();q.push_back((node){x,y,i});
    }solve(g,q);
    for (int i=1;i<=m;++i) printf("%d\n",ans[i]);
    return 0;
}

你可能感兴趣的:(边分治)