表示虚树还不是很熟练。。。
发现虫洞不是很多,对每层建虚树只建连了虫洞的那些点,每个询问跑最短路即可。
常数还没卡进。。。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=300010;
const int maxm=201000;
const int mod=3999997;
const ll inf=1e12;
int n,m,q,dl[maxm<<2],deep[maxn],dfn[maxn],f[maxn][20],ch[maxn],st[maxn],tim,num=0;
bool visit[maxm<<2];
ll dist[maxm<<2];
struct dor
{   int p1,p2,u1,u2;
}d[maxm],c;
struct edge
{int t,w;edge *next;
}*con[maxm<<2],*dor[maxm],*imp[maxm<<1],*tr[maxn],*hash[4000010];
inline int ds(int x,int y) {return deep[x]-deep[y];}
void instr(int x,int y)
{edge *p;p=new edge;p->t=y;p->next=tr[x];tr[x]=p;
}
void insimp(int x,int y)
{edge *p;p=new edge;p->t=y;p->next=imp[x];imp[x]=p;
}
int insh(ll x)
{edge *p;p=new edge;p->t=x/mod;p->w=(++num);p->next=hash[x%mod];hash[x%mod]=p;return num;
}
void inscon(int x,int y,int w)
{if(x==y) return ;edge *p;p=new edge;p->t=y;p->w=w;p->next=con[x];con[x]=p;
}
int geth(ll x)
{for(edge *p=hash[x%mod];p!=NULL;p=p->next)if(p->t==x/mod) return p->w;return -123;
}
int lca(int x,int y)
{if(deep[x]>deep[y]) swap(x,y);for(int k=19;k>=0&&deep[x]<deep[y];k--)if(deep[f[y][k]]>=deep[x]) y=f[y][k];if(x==y) return x;  for(int k=19;k>=0;k--)if(f[x][k]!=f[y][k]){x=f[x][k]; y=f[y][k];}return f[x][0];
}
void dfs1(int v)
{deep[v]=deep[f[v][0]]+1;dfn[v]=(++tim);for(edge *p=tr[v];p!=NULL;p=p->next)if(p->t!=f[v][0]){f[p->t][0]=v;dfs1(p->t);}
}
bool cmp(int a,int b)
{return dfn[a]<dfn[b];
}
void build(int v)
{int top=0;ll ad=(ll)(v-1)*n;for(edge *p=imp[v];p!=NULL;p=p->next){ch[++top]=p->t;insh(ad+p->t);}   if(top==0) return ;sort(ch+1,ch+top+1,cmp);int tmp=0;for(int i=1;i<=top;i++)if(ch[i]!=ch[tmp]) ch[++tmp]=ch[i];top=tmp;int stp=1;st[1]=ch[1];for(int i=2;i<=top;i++){while(1) {int tlca=lca(ch[i],st[stp]),last=st[stp];if(st[stp]==tlca) {st[++stp]=ch[i];break;}if(ds(st[stp-1],tlca)>=0) stp--;else {st[stp]=tlca;insh(ad+tlca);}inscon(geth(ad+last),geth(ad+st[stp]),ds(last,st[stp]));inscon(geth(ad+st[stp]),geth(ad+last),ds(last,st[stp]));}   }   for(int i=stp-1;i>0;i--){inscon(geth(ad+st[i+1]),geth(ad+st[i]),ds(st[i+1],st[i]));inscon(geth(ad+st[i]),geth(ad+st[i+1]),ds(st[i+1],st[i]));}
}
inline int nxt(int x)
{return x+1-((x+1==800000)?800000:0);
}
ll spfa(int s,int t)
{int head=1,tail=1;memset(dist,0x3f,sizeof(dist));memset(visit,0,sizeof(visit));dl[1]=s;visit[s]=1;dist[s]=0;while(head!=tail+1){int v=dl[head];for(edge *p=con[v];p!=NULL;p=p->next)if(dist[p->t]>dist[v]+p->w){dist[p->t]=dist[v]+p->w;if(!visit[p->t]){dl[(tail=nxt(tail))]=p->t;visit[p->t]=1;}}visit[dl[(head=nxt(head))]]=0;}return dist[t];
}
int main()
{freopen("m.in","r",stdin);freopen("m.out","w",stdout);scanf("%d%d%d",&n,&m,&q);for(int i=1;i<=n-1;i++){int x,y;scanf("%d%d",&x,&y);instr(x,y);instr(y,x);}f[1][0]=0;dfs1(1);for(int k=1;(1<<k)<=n;k++)for(int i=1;i<=n;i++)if(f[i][k-1]!=0) f[i][k]=f[f[i][k-1]][k-1];for(int i=1;i<=m;i++){scanf("%d%d%d%d",&d[i].p1,&d[i].u1,&d[i].p2,&d[i].u2);insimp(d[i].u1,d[i].p1);insimp(d[i].u2,d[i].p2);    }for(int i=1;i<=200000;i++)build(i);   for(int i=1;i<=m;i++){int o1=geth((ll)(d[i].u1-1)*n+d[i].p1),o2=geth((ll)(d[i].u2-1)*n+d[i].p2);inscon(o1,o2,1);inscon(o2,o1,1);}   int lst=num; for(int i=1;i<=q;i++){scanf("%d%d%d%d",&c.p1,&c.u1,&c.p2,&c.u2);ll ad1=(ll)(c.u1-1)*n,ad2=(ll)(c.u2-1)*n;int tmp;for(edge *p=imp[c.u1];p!=NULL;p=p->next){tmp=lca(c.p1,p->t);inscon(lst+1,geth(ad1+p->t),ds(c.p1,tmp)+ds(p->t,tmp));}   for(edge *p=imp[c.u2];p!=NULL;p=p->next){tmp=lca(c.p2,p->t);inscon(geth(ad2+p->t),lst+2,ds(c.p2,tmp)+ds(p->t,tmp));}if(c.u1==c.u2){tmp=lca(c.p1,c.p2);inscon(lst+1,lst+2,ds(c.p1,tmp)+ds(c.p2,tmp));}ll ans=spfa(lst+1,lst+2);lst+=2;if(ans==0x3f3f3f3f3f3f3f3f) puts("impossible");else printf("%lld\n",ans);}       return 0;
}

[2017湖南集训7-8]暗牧 虚树+最短路相关推荐

  1. 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

    题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...

  2. P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

    P3899 [湖南集训]更为厉害 若 deepb<deepa\text{deep}_b<\text{deep}_adeepb​<deepa​:c 在点 a 的子树中,根据乘法原理计算 ...

  3. 2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】

    正题 题目链接:https://ac.nowcoder.com/acm/contest/7609/C 题目大意 给出nnn个点的一棵树,mmm个时刻各有一个操作 标记一个点,每个点被标记后的每一个时刻 ...

  4. [湖南集训]更为厉害 树上主席树-以树深度为下下标建立主席树

    题意题解: 首先对于树上某个点a来说,假设点b是a的祖先(也就是在a的上面),那么答案很好计算,也就是min(k,dep[a]−1)∗(size[a]−1)min(k,dep[a]-1)*(size[ ...

  5. P3899 [湖南集训]谈笑风生(线段树合并)

    P3899 [湖南集训]谈笑风生 给定一颗以111号节点为根的树,如果a≠ba \neq ba​=b,且aaa是bbb的祖先,则aaa比bbb更厉害,如果a≠ba \neq ba​=b,且dis( ...

  6. 【2016北京集训测试赛(八)】 直径 (虚树+树的直径)

    Description 注意:时限更改为4s 题解 考虑最原始的直径求法:找到离根节点(或离其他任意一点)最远的节点far1,再从far1出发找到离far1最远的节点far2,far1至far2的距离 ...

  7. UOJ#271. 【清华集训2016】连通子树(虚树+倍增)

    传送门 题解: 注意到每种颜色个数比较少,于是建出虚树后暴力背包,用倍增维护一下虚链上的DP值即可. 所以说你只需要5个倍增数组和一些卡常技巧加上无数的小细节就可以通过这道题了. 不说了我去睡觉了. ...

  8. P3899 [湖南集训]谈笑风生

    P3899 [湖南集训]谈笑风生 题目描述 Solution 我们考虑离线询问,将询问放在相对应的子树ppp中计算答案. 显然a,b,ca,b,ca,b,c的位置关系有两种情况: bbb是aaa的祖先 ...

  9. 2020牛客多校第一场B虚树+质数筛+换根dp

    题目大意: 1.可以发现阶乘增长是很快的所以你要把整颗树建立出来是不实际的. 2.我们可以假设这棵树已经建出来出来了我们应该怎么搞 首先很明显是一个树形dp, 我们设dp[j],是以j为u到其他点距离 ...

  10. [WC2018]通道——边分治+虚树+树形DP

    题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...

最新文章

  1. 最新汇总!这些高校已确定开学时间!
  2. python怎么做折线图_python怎么画折线图
  3. python 调用linux命令-python3调用linux命令——Subprocess
  4. Android多线程分析之二:Thread的实现
  5. mybatis 调用存储过程_你真的该进来了解下MyBatis的SQL工作流程了
  6. python画玫瑰曲线_「风向玫瑰图」python绘制风向玫瑰图和污染物玫瑰图 - seo实验室...
  7. 深度学习入门学习路线及好课推荐
  8. 支付宝交易行为数据分析
  9. sentencePiece入门小结
  10. 证券投资深度学习_基于风险中性的深度学习选股策略
  11. 2020-05-25
  12. dxp全称_DXP企业标志logo设计,品牌vi设计策划
  13. G2:一个由纯 javascript 编写、强大的语义化图表生成工具
  14. C++ P1282 多米诺骨牌
  15. AWS云计算技术架构探索系列之一-开篇
  16. Sequelize 数据迁移
  17. STM32+BM8563时钟芯片不走时问题解决(含配置代码)
  18. 编程行业未来趋势如何
  19. linux 内核 fork,Linux fork()一个进程内核态的变化
  20. mysql 申明变量及赋值_mysql申明变量以及赋值

热门文章

  1. 渗透测试技巧总结更新篇2
  2. Photoshop 套索工具抠图
  3. phyton 100题(更新中)
  4. 自古英雄出少年,22岁中国小哥哥入选Nature十大人物
  5. python:利用pandas进行绘图(总结)绘图格式
  6. 质量功能配置(QFD)矩阵
  7. Xenu's Link Sleuth 的使用
  8. [实战]制作简单的公众号二维码关注图
  9. 用OneDrive生成音乐外链和图片外链
  10. 图片裁切以及图片预览的过程