BZOJ4449 : [Neerc2015]Distance on Triangulation

首先拓扑,每次取出度数为$2$的点,这样可以把所有三角形都找到。

那么建出对偶图,会发现是一棵树。

对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心$3$个点分别做一次BFS。

对于每个询问,如果不经过重心这个区域,那么递归求解,否则用BFS的结果回答即可。

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=50010,M=100010,U=M*20;
int n,m,i,x,y,z,d[N],g[N],v[N<<2],nxt[N<<2],ed,vis[N],h,t,q[N],ans[M];
struct Q{int x,y;}que[M];
inline void read(int&a){char c;while(!(((c=getchar())>=‘0‘)&&(c<=‘9‘)));a=c-‘0‘;while(((c=getchar())>=‘0‘)&&(c<=‘9‘))(a*=10)+=c-‘0‘;}
inline void add(int x,int y){d[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
namespace Graph{
int n,m,i,id[N][3],g[N],v[N<<1],nxt[N<<1],ok[N<<1],ed;
int all,f[N],son[N],now,pos[N],last[N],cur,dis[3][N];
int G[N],V[U],NXT[U],ED,p[N*3],cnt;
struct E{int x,y,p;E(){}E(int _x,int _y,int _p){x=_x,y=_y,p=_p;}}e[N*3];
inline bool cmp(const E&a,const E&b){return a.x==b.x?a.y<b.y:a.x<b.x;}
inline void add(int x,int y){
  v[++ed]=y;ok[ed]=1;nxt[ed]=g[x];g[x]=ed;
  v[++ed]=x;ok[ed]=1;nxt[ed]=g[y];g[y]=ed;
}
inline void ADD(int x,int y){V[++ED]=y;NXT[ED]=G[x];G[x]=ED;}
inline void newedge(int x,int y,int z){
  n++;
  id[n][0]=x,id[n][1]=y,id[n][2]=z;
  e[++m]=E(min(x,y),max(x,y),n);
  e[++m]=E(min(x,z),max(x,z),n);
  e[++m]=E(min(y,z),max(y,z),n);
}
void findroot(int x,int y){
  son[x]=1;f[x]=0;
  for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y){
    findroot(v[i],x);
    son[x]+=son[v[i]];
    if(son[v[i]]>f[x])f[x]=son[v[i]];
  }
  if(all-son[x]>f[x])f[x]=all-son[x];
  if(f[x]<f[now])now=x;
}
void dfs(int x,int y,int z){
  for(int i=0;i<3;i++){
    pos[id[x][i]]=z;
    last[id[x][i]]=cur;
    p[++cnt]=id[x][i];
  }
  for(int i=g[x];i;i=nxt[i])if(ok[i]&&v[i]!=y)dfs(v[i],x,z);
}
inline void bfs(int S,int*d){
  int i,x,y,h,t;static int q[N];
  for(i=1;i<=cnt;i++)d[p[i]]=U;
  d[q[h=t=1]=S]=0;
  while(h<=t)for(i=::g[x=q[h++]];i;i=::nxt[i]){
    y=::v[i];
    if(d[y]<U||last[y]<cur)continue;
    d[q[++t]=y]=d[x]+1;
  }
}
void solve(int x){
  if(!G[x])return;
  f[0]=all=son[x],findroot(x,now=0);
  int i,j,A,B;
  cur++;
  for(cnt=0,i=g[now];i;i=nxt[i])if(ok[i])dfs(v[i],now,v[i]);
  for(i=0;i<3;i++){
    p[++cnt]=A=id[now][i];
    pos[A]=now,last[A]=cur;
  }
  for(i=0;i<3;i++)bfs(id[now][i],dis[i]);
  for(cnt=0,i=G[x];i;i=NXT[i])p[++cnt]=V[i];G[x]=0;
  for(i=1;i<=cnt;i++){
    A=que[p[i]].x,B=que[p[i]].y;
    if(pos[A]==pos[B])
      if(pos[A]==now)ans[p[i]]=1;
      else ADD(pos[A],p[i]);
    else for(j=0;j<3;j++)ans[p[i]]=min(ans[p[i]],dis[j][A]+dis[j][B]);
  }
  for(i=g[now];i;i=nxt[i])if(ok[i])ok[i^1]=0,solve(v[i]);
}
void Main(){
  sort(e+1,e+m+1,cmp);
  for(ed=i=1;i<m;i++)if(e[i].x==e[i+1].x&&e[i].y==e[i+1].y)add(e[i].p,e[i+1].p);
  son[1]=n;solve(1);
}
}
int main(){
  read(n);
  for(i=1;i<n;i++)add(i,i+1),add(i+1,i);
  add(1,n),add(n,1);
  for(i=1;i<=n-3;i++)read(x),read(y),add(x,y),add(y,x);
  for(h=i=1;i<=n;i++)if(d[i]==2)q[++t]=i;
  while(h<=t){
    x=q[h++];
    if(d[x]!=2)continue;
    vis[x]=1,y=0;
    for(i=g[x];i;i=nxt[i])if(!vis[v[i]]){
      if(y)z=v[i];else y=v[i];
      if((--d[v[i]])==2)q[++t]=v[i];
    }
    Graph::newedge(x,y,z);
  }
  read(m);
  for(i=1;i<=m;i++){
    read(x),read(y);
    if(x!=y)que[i].x=x,que[i].y=y,Graph::ADD(1,i),ans[i]=U;
  }
  Graph::Main();
  for(i=1;i<=m;i++)printf("%d\n",ans[i]);
  return 0;
}

  

时间: 2024-10-10 20:24:20

BZOJ4449 : [Neerc2015]Distance on Triangulation的相关文章

bzoj 4449: [Neerc2015]Distance on Triangulation

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). Outpu

Signed Distance Field Shadow in Unity

0x00 前言 最近读到了一个今年GDC上很棒的分享,是Sebastian Aaltonen带来的利用Ray-tracing实现一些有趣的效果的分享. 其中有一段他介绍到了对Signed Distance Field Shadow的改进,主要体现在消除SDF阴影的一些artifact上. 第一次看到Signed Distance Field Shadow是在大神Inigo Quilez的博客上,较传统的阴影实现方式,例如shadow map,视觉效果要好很多.可以看到下图中物体的阴影随着距离由近

461.求两个数字转成二进制后的“汉明距离” Hamming Distance

public class Solution { public int HammingDistance(int x, int y) { int distance = 0; string sX = Convert.ToString(x, 2); string sY = Convert.ToString(y, 2); int maxLength = Math.Max(sX.Length, sY.Length); //填充0,使两个字符串右对齐 sX = sX.PadLeft(maxLength, '0

LeetCode 72 Edit Distance

Given two words word1 and word2, find the minimum number of steps required to convert word1 to word2. (each operation is counted as 1 step.) You have the following 3 operations permitted on a word: a) Insert a character b) Delete a character c) Repla

461. Hamming Distance

The Hamming distance between two integers is the number of positions at which the corresponding bits are different. Given two integers x and y, calculate the Hamming distance. Note:0 ≤ x, y < 2^31. Example: Input: x = 1, y = 4 Output: 2 Explanation:

搬土距离(Earth Mover&#39;s Distance)

搬土距离(The Earth Mover's Distance,EMD)最早由Y. Rubner在1999年的文章<A Metric for Distributions with Applications to Image Databases>中提出,它是归一化的从一个分布变为另一个分布的最小代价,因此可用于表征两个分布之间的距离. 例如,对于图像而言,它可以看做是由色调.饱和度.亮度三个分量组成,每个分量的直方图就是一个分布.不同的图像对应的直方图不同,因此图像之间的距离可以用直方图的距离表

distance.c

1 #include "stdio.h" 2 #include "string.h" 3 #include "math.h" 4 #include "malloc.h" 5 6 const long long Max_size = 2000;//输入字符串的最大长度,可以由单个词条和多个词条组成 7 const long long N = 40;//输出与某个单词最接近的N个词 8 const long long Max_w

[Locked] One Edit Distance

One Edit Distance Given two strings S and T, determine if they are both one edit distance apart. 分析: 编辑距离复杂度为O(MN),而本题显然不能用这么高的复杂度:首先,可以通过判断两个字符串是否等长来决定用增一位.减一位.替换一位这三种方法之一来使得两个字符串等同,如果都不行,就return false:然后同时遍历S和T,第一次遇到不匹配的,就用刚才判断出的方法拯救一下:第二次还遇到不匹配的,就

I - Long Distance Racing(第二季水)

Description Bessie is training for her next race by running on a path that includes hills so that she will be prepared for any terrain. She has planned a straight path and wants to run as far as she can -- but she must be back to the farm within M se