题目描述
在 Dato3 的世界里,英雄们通过对量子力学的研究,发现了世界上其实存在
着无数个位面——即是也被称作平行宇宙的存在。
位面有无数多个,每个位面中包含 n 颗行星,由 n−1 个虫洞链接。同一个位
面中的任意两颗行星间有唯一的虫洞路径。
量子力学之父巴拉森指出:“每个位面都看起来差不多。”,揭示了所有位面中
的虫洞都是相同的的道理。也即,如果某个位面中在行星 q1 和 q2 之间有虫洞,那
么任意位面中 q1 和 q2 间都有虫洞。位面从 1 开始编号,一个位面中的行星编号为
1 到 n 。因此使用位面和行星的编号就能唯一确定一颗行星。
艾欧使用它最近获得的至宝”Portal Gun” 建造了 m 个可以双向通行的传送门。
每个传送门用四个整数 p1; u1; p2; u2 描述,代表可以让人们在 u1 位面的 p1 行星和
u2 位面的 p2 行星间移动。通过虫洞或者传送门移动都需要花费 1 单位的时间。
负责星际医疗协助的暗影牧师戴泽希望你能帮忙计算行星间的最短路,共有 q
个询问需要你回答。
2.2 输入格式
输入的第一行包含三个整数 n; m 和 q ,分别代表单个位面中的行星数、传送
门的数量,以及询问的数量。
接下来 n−1 行描述位面中的虫洞,每行包含两个整数,代表一个虫洞所连接
的两个行星。
接下来 m 行描述传送门,每行包含四个整数 p1; u1; p2; u2 。
接下来 q 行描述询问,每行包含四个整数 p1; u1; p2; u2 ,你需要回答从 u1 位
面的 p1 行星到 u2 位面的 p2 行星的最短距离。
4
2.3 输出格式
对于每个询问,输出一行,包含一个整数,代表最短路径的耗时。如果无法到
达,则输出“ impossible”(不含引号)。
2.4 样例输入
3 3 3
1 2
2 3
1 1 1 3
3 1 3 2
1 2 3 3
2 1 2 2
2 1 2 3
1 2 3 2
2.5 样例输出
3 4 2
2.6 数据范围
对于 30% 的数据, 1 ≤ n ≤ 1000; 1 ≤ m ≤ 3000; 1 ≤ u1; u2 ≤ 1000 。
对于另外 20% 的数据,一个位面中的行星形成一条链。
对于 100% 的数据, 1 ≤ n ≤ 300000; 1 ≤ m ≤ 100000; 1 ≤ q ≤ 10; 1 ≤ p1; p2 ≤
n; 1 ≤ u1; u2 ≤ 200000 。
5
保证由虫洞和传送门形成的整张图不含重边或自环。

题解:

弄u1棵树显然是不现实的,于是我们可以改变spfa的方式,直接把每一个位面中的关键点都存起来,然后直接以这些关键点跑spfa

其他的点可以不用管,然后转移之间用树上距离即可 建图可以hash,距离直接树剖lca即可

 #include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#pragma comment(linker, "/STACK:1048576000,1048576000")
using namespace std;
const int N=,M=;
typedef long long ll;
const ll INF=2e15;
int gi(){
int str=;char ch=getchar();
while(ch>'' || ch<'')ch=getchar();
while(ch>='' && ch<='')str=(str<<)+(str<<)+ch-,ch=getchar();
return str;
}
int head[N],num=,ids=,bel[N],id[N];
struct Lin{
int next,to;
}a[N<<];
int Head[N],nm=;
struct hash{
int next,id;ll to;
}b[N<<];
bool vt[N*];
void adds(int x,int y,int id){
ll cnt=(ll)(x*+y);int k=cnt%N;
b[++nm].next=Head[k];
b[nm].to=cnt;
b[nm].id=id;
Head[k]=nm;
}
int find(int x,int y){
ll cnt=(ll)(x*+y);int k=cnt%N;
for(int i=Head[k];i;i=b[i].next){
if(b[i].to==cnt)return b[i].id;
}
return ;
}
void init(int x,int y){
a[++num].next=head[x];
a[num].to=y;
head[x]=num;
}
void addedge(int x,int y){
init(x,y);init(y,x);
}
int n,m,Q;
vector<int>t[N];
vector<int>key[M];
int size[N],top[N],son[N],dep[N],fa[N];
void dfs1(int x){
int u;
size[x]=;
for(int i=,sz=t[x].size();i<sz;i++){
u=t[x][i];
if(dep[u])continue;
dep[u]=dep[x]+;fa[u]=x;
dfs1(u);
size[x]+=size[u];
if(size[u]>size[son[x]])son[x]=u;
}
}
void dfs2(int x,int tp){
top[x]=tp;
int u;
if(son[x])dfs2(son[x],tp);
for(int i=,sz=t[x].size();i<sz;i++){
u=t[x][i];
if(u!=son[x] && u!=fa[x])dfs2(u,u);
}
}
int query(int x,int y){
int tx=dep[x]+dep[y];
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])
swap(x,y);
x=fa[top[x]];
}
if(dep[x]>dep[y])swap(x,y);
return tx-(dep[x]<<);
}
int q[N*],mod=N*;int vis[N];ll f[N];
void spfa()
{
int x1=gi(),u1=gi(),y1=gi(),u2=gi(),u,x;
for(int i=;i<=ids;i++)f[i]=INF,vis[i]=false;
int t=,sum=;ll dist;
for(int i=,sz=key[u1].size();i<sz;i++){
u=key[u1][i];
f[u]=query(id[u],x1);
q[++sum]=u;
vis[u]=true;
}
while(t!=sum){
t++;t%=mod;x=q[t];
for(int i=head[x];i;i=a[i].next){
u=a[i].to;
if(f[x]+<f[u]){
f[u]=f[x]+;
if(vt[vis[u]])vt[vis[u]]=false;
if(!vis[u])sum++,sum%=mod,q[sum]=u,vis[u]=sum,vt[sum]=false;
}
}
if(!vt[vis[x]])
for(int i=,sz=key[bel[x]].size();i<sz;i++){
u=key[bel[x]][i];
if(u==x)continue;
dist=query(id[u],id[x]);
if(f[x]+dist<f[u]){
f[u]=f[x]+dist;
if(!vis[u])sum++,sum%=mod,q[sum]=u,vis[u]=sum,vt[sum]=true;
}
}
vis[x]=;
}
ll ans=2e15;
for(int i=,sz=key[u2].size();i<sz;i++){
u=key[u2][i];
dist=query(id[u],y1);
if(f[u]+dist<ans)ans=f[u]+dist;
}
if(u1==u2)ans=min(ans,(ll)query(x1,y1));
if(ans!=2e15)printf("%lld\n",ans);
else printf("impossible\n");
}
int main()
{
freopen("m.in","r",stdin);
freopen("m.out","w",stdout);
n=gi();m=gi();Q=gi();
int x,y;
for(int i=;i<n;i++){
x=gi();y=gi();
t[x].push_back(y);t[y].push_back(x);
}
dep[]=;
dfs1();dfs2(,);
int u1,u2,xx,yy;
for(int i=;i<=m;i++){
x=gi();u1=gi();y=gi();u2=gi();
xx=find(u1,x);yy=find(u2,y);
if(!xx)xx=++ids,key[u1].push_back(ids),bel[ids]=u1,id[ids]=x,adds(u1,x,ids);
if(!yy)yy=++ids,key[u2].push_back(ids),bel[ids]=u2,id[ids]=y,adds(u2,y,ids);
addedge(xx,yy);
}
while(Q--)spfa();
return ;
}

暗牧 (m)的更多相关文章

  1. dota玩家与英雄契合度的计算器,python语言scrapy爬虫的使用

    首发:个人博客,更新&纠错&回复 演示地址在这里,代码在这里. 一个dota玩家与英雄契合度的计算器(查看效果),包括两部分代码: 1.python的scrapy爬虫,总体思路是pag ...

随机推荐

  1. 团队作业7——第二次项目冲刺(Beta版本12.10)

    项目每个成员的进展.存在问题.接下来两天的安排. 已完成的内容:头像功能原型设计.头像裁剪功能.头像上传功能.测试 计划完成的内容:头像功能测试.bug修复 每个人的工作 (有work item 的I ...

  2. 《Language Implementation Patterns》之 强类型规则

    语句的语义取决于其语法结构和相关符号:前者说明了了要"做什么",后者说明了操作"什么对象".所以即使语法结构正确的,如果被操作的对象不合法,语句也是不合法的.语 ...

  3. Beta冲刺Day6

    项目进展 李明皇 今天解决的进度 进行前后端联动调试 明天安排 完善程序运行逻辑 林翔 今天解决的进度 服务器端发布消息,删除消息,检索消息,个人发布的action 明天安排 图片功能遇到问题,微信小 ...

  4. 构建微服务开发环境3————Java应用的优秀管理工具Maven的下载安装及配置

    [内容指引] 下载安装包: MacOS下Maven的安装及配置: Windows下Maven的安装及配置. 一.下载安装包 进入Maven的官方下载地址:http://maven.apache.org ...

  5. 【nodejs】安装browser-sync 遇到错误提示

    首先我用的是mac电脑在我执行安装browser-sync时遇到如下问题: 因为不被允许所以我只能不安装全局了: 但是又出现了如下的新问题 纠结了半个小时,终于知道为什么会出现这个问题了, node只 ...

  6. git(一)快速入门

    1.设置用户名 git config --global user.name '你的用户名' ​ 2.设置用户名邮箱 git config --global user.email '你的邮箱' ​ 3. ...

  7. nyoj 还是回文

    还是回文 时间限制:2000 ms | 内存限制:65535 KB 难度:3 描述 判断回文串很简单,把字符串变成回文串也不难.现在我们增加点难度,给出一串字符(全部是小写字母),添加或删除一个字符, ...

  8. css中的em 简单教程 -- 转

    先附上原作的地址: https://www.w3cplus.com/css/px-to-em 习惯性的复制一遍~~~~ -------------------------------我是分界线---- ...

  9. vmware 12 安装 mac os 10.12正式版

    1.首先下载安装vmware 12 pro ,将VT打开(虚拟功能,以前安装过虚拟机点的同学可忽略). 2.下载mac ox 10.12正式版镜像文件(cdr后缀). 3.下载Unlocker208( ...

  10. api-gateway实践(07)新服务网关 - 手动发布

    应用地址:http://10.110.20.191:8080/api-gateway-engine/ 一.准备工作 1.xshell登陆云主机 1.1.配置链接 1.2.链接成功 1.3.关闭防火墙 ...