您的位置:首页 > 其它

[点分治 离线] BZOJ 4449 [Neerc2015]Distance on Triangulation

2017-03-06 20:43 651 查看
其实简单的找一条边然后分成两半

被我硬生生写成对偶图点分治分成三块 233

就把所有询问一起处理

点分治时 如果两个点在同一侧 就递归 否则对三个点bfs就能知道最短路径

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#define cl(x) memset(x,0,sizeof(x))
using namespace std;
typedef pair<int,int> abcd;

inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

const int N=100005;

struct edge{
int u,v,next;
}G[N<<3];
int head
,head2
,inum;
inline void add(int u,int v,int *head){
int p=++inum; G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
inline void link(int u,int v,int *head){
add(u,v,head); add(v,u,head);
}
#define V G[p].v
int n;
int deg
;
int pt
[3];

map<abcd,int> ed;
inline void BT(){
static int Q
,l,r,rem
;
l=r=-1; cl(rem);
for (int i=1;i<=n;i++) if (deg[i]==2) Q[++r]=i;
for (int i=1;i<=n-2;i++){
int u=Q[++l],a[3]; rem[u]=1;
*a=0;
for (int p=head[u];p;p=G[p].next)
if (!rem[V])
a[++*a]=V;
pt[i][0]=u; pt[i][1]=a[1]; pt[i][2]=a[2];
if ((--deg[a[1]])==2) Q[++r]=a[1];
if ((--deg[a[2]])==2) Q[++r]=a[2];
}
for (int s=1;s<=n-2;s++){
for (int i=0;i<3;i++)
for (int j=0;j<i;j++){
int u=pt[s][i],v=pt[s][j];
if (u>v) swap(u,v);
if (ed.count(abcd(u,v)))
link(s,ed[abcd(u,v)],head2);
else
ed[abcd(u,v)]=s;
}
}
}

int del
;

int sum,minv,rt;
int size
;
inline void Root(int u,int fa){
size[u]=1; int maxv=0;
for (int p=head2[u];p;p=G[p].next)
if (V!=fa && !del[V])
Root(V,u),size[u]+=size[V],maxv=max(maxv,size[V]);
maxv=max(maxv,sum-size[u]);
if (maxv<minv) minv=maxv,rt=u;
}

int c
,col=4;
int ins
,clk;
int dis[3]
;

inline void bfs(int S,int *dis){
static int Q
,l,r;
l=r=-1; ++clk;
Q[++r]=S; dis[S]=0; ins[S]=clk;
while (l<r){
int u=Q[++l];
for (int p=head[u];p;p=G[p].next)
if (c[V]==c[u] && ins[V]!=clk){
dis[V]=dis[u]+1;
ins[V]=clk;
Q[++r]=V;
}
}
}

int Col;
inline void color(int u,int fa){
size[u]=1;
for (int i=0;i<3;i++) c[pt[u][i]]=Col;
for (int p=head2[u];p;p=G[p].next)
if (V!=fa && !del[V])
color(V,u),size[u]+=size[V];
}

struct event{
int u,v,idx;
event(int u=0,int v=0,int idx=0):u(u),v(v),idx(idx){ }
};

int Ans[N<<1];

inline void Divide(int u,vector<event> &que){
if (que.empty()) return;
del[u]=1;
for (int i=0;i<3;i++)
bfs(pt[u][i],dis[i]);
Col=0;
for (int p=head2[u];p;p=G[p].next)
if (!del[V]){
Col++;
color(V,0);
}
for (int i=0;i<3;i++) c[pt[u][i]]=0;
vector<event> vec[4];
for (int i=0;i<(int)que.size();i++){
int a=que[i].u,b=que[i].v,idx=que[i].idx;
if (c[a]==0){
for (int j=0;j<3;j++)
if (a==pt[u][j])
Ans[idx]=dis[j][b];
}else if (c[b]==0){
for (int j=0;j<3;j++)
if (b==pt[u][j])
Ans[idx]=dis[j][a];
}else if (c[a]!=c[b]){
Ans[idx]=1<<30;
for (int j=0;j<3;j++)
Ans[idx]=min(Ans[idx],dis[j][a]+dis[j][b]);
}else{
vec[c[a]].push_back(que[i]);
}
}
for (int p=head2[u],i=0;p;p=G[p].next)
if (!del[V]){
Col=++col; color(V,0);
sum=size[V]; minv=1<<30;
Root(V,0);
Divide(rt,vec[++i]);
}
}

int main(){
int iu,iv,Q;
freopen("drive.in","r",stdin);
freopen("drive.out","w",stdout);
read(n);
for (int i=1;i<n;i++) link(i,i+1,head);
link(n,1,head);
for (int i=1;i<=n;i++) deg[i]=2;
for (int i=1;i<=n-3;i++)
read(iu),read(iv),link(iu,iv,head),deg[iu]++,deg[iv]++;
BT();
read(Q);
vector<event> vec;
for (int i=1;i<=Q;i++)
read(iu),read(iv),vec.push_back(event(iu,iv,i));
sum=n-2; minv=1<<30;
Root(1,0);
for (int i=1;i<=n;i++) c[i]=col;
Divide(rt,vec);
for (int i=1;i<=Q;i++)
printf("%d\n",Ans[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: