题目链接

圆方树。做题思路不写了。。

就是当LCA是方点时跳进那个环可以分类讨论一下用树剖而不必须用倍增:

如果v是u的(唯一的那个)重儿子,那么u的DFS序上+1的点即是要找的;否则v会引出一条新的链。

不用圆方树的做法(代码错了不想改了,但是能A)

//3876kb	148ms(Rank6!)
#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 50000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
const int N=10005<<1,M=N<<2;//点数!(方点) int n,m,Q,tot,Index,dfn[N],low[N],fa[N],dis[N],cdis[N],sz[N],son[N],dep[N],top[N],ref[N],cnt;
char IN[MAXIN],*SS=IN,*TT=IN;
struct Edge
{
int Enum,H[N],nxt[M],to[M],val[M];
inline void AddEdge(int u,int v,int w){
to[++Enum]=v, nxt[Enum]=H[u], val[Enum]=w, H[u]=Enum;
to[++Enum]=u, nxt[Enum]=H[v], val[Enum]=w, H[v]=Enum;
}
}g,t; inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
void Build(int u,int v,int d)//v->...->u->v
{
for(int i=v; i!=u; i=fa[i]) cdis[i]=d, d+=dis[i];//直接用个dis[]记来时边的权值
cdis[++tot]=d/*length of circle*/, t.AddEdge(tot,u,0);
for(int i=v; i!=u/*fa[u]*/; i=fa[i]) t.AddEdge(tot,i,std::min(cdis[i],d-cdis[i]));
}
void Tarjan(int x)
{
dfn[x]=low[x]=++Index;
for(int v,i=g.H[x]; i; i=g.nxt[i])
if(g.to[i]!=fa[x])
{
if(!dfn[v=g.to[i]])
fa[v]=x, dis[v]=g.val[i], Tarjan(v), low[x]=std::min(low[x],low[v]);
else low[x]=std::min(low[x],dfn[v]);
if(low[v]>dfn[x]) t.AddEdge(x,v,g.val[i]);//Round point
}
for(int v,i=g.H[x]; i; i=g.nxt[i])
if(fa[v=g.to[i]]!=x && dfn[v]>dfn[x]) Build(x,v,g.val[i]);//Square point
}
void DFS1(int x)
{
int mx=0; sz[x]=1;
for(int v,i=t.H[x]; i; i=t.nxt[i])
if((v=t.to[i])!=fa[x])
{
dep[v]=dep[x]+1, dis[v]=dis[x]+t.val[i], fa[v]=x, DFS1(v), sz[x]+=sz[v];
if(sz[v]>mx) mx=sz[v], son[x]=v;
}
}
void DFS2(int x,int tp)
{
top[x]=tp, ref[dfn[x]=++cnt]=x;
if(son[x]){
DFS2(son[x],tp);
for(int i=t.H[x]; i; i=t.nxt[i])
if(t.to[i]!=fa[x]&&t.to[i]!=son[x]) DFS2(t.to[i],t.to[i]);
}
}
int LCA(int u,int v)
{
while(top[u]!=top[v]) dep[top[u]]>dep[top[v]]?u=fa[top[u]]:v=fa[top[v]];
return dep[u]<dep[v]?u:v;
}
int Get_p(int u,int lca)
{
int las=u;
while(top[u]!=top[lca]) u=fa[las=top[u]];
return u==lca?las:ref[dfn[lca]+1];
} int main()
{
tot=n=read(),m=read(),Q=read();
for(int u,v,i=1; i<=m; ++i) u=read(),v=read(),g.AddEdge(u,v,read());
Tarjan(1), dis[1]=fa[1]=0, DFS1(1), DFS2(1,1);
int u,v,w,p1,p2;
while(Q--)
{
u=read(),v=read(),w=LCA(u,v);
if(w<=n) printf("%d\n",dis[u]+dis[v]-(dis[w]<<1));//没有负边,圆上顺序。。无所谓了。
else p1=Get_p(u,w), p2=Get_p(v,w), printf("%d\n",dis[u]-dis[p1]+dis[v]-dis[p2]+std::min(std::abs(cdis[p2]-cdis[p1]),cdis[w]-std::abs(cdis[p2]-cdis[p1])));//这是cdis[p]不是cdis[u/v]!mmpzz错误调了半个多小时
}
return 0;
}

BZOJ.2125.最短路(仙人掌 圆方树)的更多相关文章

  1. 仙人掌&圆方树学习笔记

    仙人掌&圆方树学习笔记 1.仙人掌 圆方树用来干啥? --处理仙人掌的问题. 仙人掌是啥? (图片来自于\(BZOJ1023\)) --也就是任意一条边只会出现在一个环里面. 当然,如果你的图 ...

  2. 仙人掌 && 圆方树 && 虚树 总结

    仙人掌 && 圆方树 && 虚树 总结 Part1 仙人掌 定义 仙人掌是满足以下两个限制的图: 图完全联通. 不存在一条边处在两个环中. 其中第二个限制让仙人掌的题做 ...

  3. 仙人掌&圆方树

    仙人掌&圆方树 Tags:图论 [x] [luogu4320]道路相遇 https://www.luogu.org/problemnew/show/P4320 [ ] [SDOI2018]战略 ...

  4. BZOJ.2125.最短路(仙人掌 最短路Dijkstra)

    题目链接 多次询问求仙人掌上两点间的最短路径. 如果是在树上,那么求LCA就可以了. 先做着,看看能不能把它弄成树. 把仙人掌看作一个图(实际上就是),求一遍根节点到每个点的最短路dis[i]. 对于 ...

  5. 2018.07.25 bzoj2125: 最短路(圆方树+倍增)

    传送门 人生的第一道仙人掌. 这道题求是仙人掌上的最短路. 先建出圆方树,然后用倍增跑最短路,当lca" role="presentation" style=" ...

  6. UOJ.87.mx的仙人掌(圆方树 虚树)(未AC)

    题目链接 本代码10分(感觉速度还行..). 建圆方树,预处理一些东西.对询问建虚树. 对于虚树上的圆点直接做:对于方点特判,枚举其所有儿子,如果子节点不在该方点代表的环中,跳到那个点并更新其val, ...

  7. BZOJ.5329.[SDOI2018]战略游戏(圆方树 虚树)

    题目链接 显然先建圆方树,方点权值为0圆点权值为1,两点间的答案就是路径权值和减去起点终点. 对于询问,显然可以建虚树.但是只需要计算两关键点间路径权值,所以不需要建出虚树.统计DFS序相邻的两关键点 ...

  8. bzoj 2125 最短路——仙人掌两点间最短路

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2125 因为看了TJ又抄了标程,现在感觉还是轻飘飘的……必须再做一遍. 两点间的情况: 1.直 ...

  9. 图论杂项细节梳理&模板(虚树,圆方树,仙人掌,欧拉路径,还有。。。)

    orzYCB 虚树 %自为风月马前卒巨佬% 用于优化一类树形DP问题. 当状态转移只和树中的某些关键点有关的时候,我们把这些点和它们两两之间的LCA弄出来,以点的祖孙关系连成一棵新的树,这就是虚树. ...

随机推荐

  1. python面向对象——类

    from:http://www.runoob.com/python3/python3-class.html Python3 面向对象 Python从设计之初就已经是一门面向对象的语言,正因为如此,在P ...

  2. Intent 对象在 Android 开发中的应用

    转自(http://www.ibm.com/developerworks/cn/opensource/os-cn-android-intent/) Android 是一个开放性移动开发平台,运行在该平 ...

  3. 05 Diagnostics 诊断

    Diagnostics 诊断 Introduction 介绍 Profiling 分析 Tracing 跟踪 Debugging 调试 Runtime statistics and events 运行 ...

  4. Python爬虫之三种网页抓取方法性能比较

    下面我们将介绍三种抓取网页数据的方法,首先是正则表达式,然后是流行的 BeautifulSoup 模块,最后是强大的 lxml 模块. 1. 正则表达式   如果你对正则表达式还不熟悉,或是需要一些提 ...

  5. 使用apt-get安装Nginx

    Ubuntu 18.04,Nginx 1.14.0, 一直想在Linux上安装Nginx,一直没找到契机,很大原因是自己不熟悉,Ubuntu没安装好吧!今天下午学习了Ubuntu安装软件的一些资料,那 ...

  6. os.path.isdir(path)异常

    Window 10家庭中文版,Python 3.6.4, 当一个路径以多个斜杠(/)或反斜杠字符(\\)结尾时,os.path.isdir(path)函数仍然将它们判断为目录: >>> ...

  7. js数据绑定(模板引擎原理)

    <div> <ul id="list"> <li>11111111111</li> <li>22222222222< ...

  8. 下一代Android打包工具,100个渠道包只需要10秒钟 https://github.com/mcxiaoke

    https://github.com/mcxiaoke/packer-ng-plugin https://github.com/Meituan-Dianping/walle https://githu ...

  9. CF401D 【Roman and Numbers】

    题意将n(n<=10^18)的各位数字重新排列(不允许有前导零)  求  可以构造几个mod m等于0的数字解法状压f[S][k] 表示选用的位数集合为S,mod m 为k的方案数注意不能有前导 ...

  10. 打印数据的字节(十六进制)表示-c语言代码

    先取数据地址,转换成单字节长度的类型(unsigned char)的指针,然后按照十六进制逐字节打印即可,格式为“%.2x”. sizeof()函数获取数据的字节数. /* $begin show-b ...