BZOJ4449 : [Neerc2015]Distance on Triangulation
首先拓扑,每次取出度数为2的点,这样可以把所有三角形都找到。
那么建出对偶图,会发现是一棵树。
对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心3个点分别做一次BFS。
对于每个询问,如果不经过重心这个区域,那么递归求解,否则用BFS的结果回答即可。
时间复杂度O(nlogn)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #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; } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术