暗牧 (m)

题目描述
在 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即可

 

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <vector>
  8 #include <queue>
  9 #pragma comment(linker, "/STACK:1048576000,1048576000")
 10 using namespace std;
 11 const int N=400005,M=200005;
 12 typedef long long ll;
 13 const ll INF=2e15;
 14 int gi(){
 15     int str=0;char ch=getchar();
 16     while(ch>'9' || ch<'0')ch=getchar();
 17     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
 18     return str;
 19 }
 20 int head[N],num=0,ids=0,bel[N],id[N];
 21 struct Lin{
 22     int next,to;
 23 }a[N<<2];
 24 int Head[N],nm=0;
 25 struct hash{
 26     int next,id;ll to;
 27 }b[N<<1];
 28 bool vt[N*10];
 29 void adds(int x,int y,int id){
 30     ll cnt=(ll)(x*200000+y);int k=cnt%N;
 31     b[++nm].next=Head[k];
 32     b[nm].to=cnt;
 33     b[nm].id=id;
 34     Head[k]=nm;
 35 }
 36 int find(int x,int y){
 37     ll cnt=(ll)(x*200000+y);int k=cnt%N;
 38     for(int i=Head[k];i;i=b[i].next){
 39         if(b[i].to==cnt)return b[i].id;
 40     }
 41     return 0;
 42 }
 43 void init(int x,int y){
 44     a[++num].next=head[x];
 45     a[num].to=y;
 46     head[x]=num;
 47 }
 48 void addedge(int x,int y){
 49     init(x,y);init(y,x);
 50 }
 51 int n,m,Q;
 52 vector<int>t[N];
 53 vector<int>key[M];
 54 int size[N],top[N],son[N],dep[N],fa[N];
 55 void dfs1(int x){
 56     int u;
 57     size[x]=1;
 58     for(int i=0,sz=t[x].size();i<sz;i++){
 59         u=t[x][i];
 60         if(dep[u])continue;
 61         dep[u]=dep[x]+1;fa[u]=x;
 62         dfs1(u);
 63         size[x]+=size[u];
 64         if(size[u]>size[son[x]])son[x]=u;
 65     }
 66 }
 67 void dfs2(int x,int tp){
 68     top[x]=tp;
 69     int u;
 70     if(son[x])dfs2(son[x],tp);
 71     for(int i=0,sz=t[x].size();i<sz;i++){
 72         u=t[x][i];
 73         if(u!=son[x] && u!=fa[x])dfs2(u,u);
 74     }
 75 }
 76 int query(int x,int y){
 77     int tx=dep[x]+dep[y];
 78     while(top[x]!=top[y]){
 79         if(dep[top[x]]<dep[top[y]])
 80             swap(x,y);
 81         x=fa[top[x]];
 82     }
 83     if(dep[x]>dep[y])swap(x,y);
 84     return tx-(dep[x]<<1);
 85 }
 86 int q[N*10],mod=N*10;int vis[N];ll f[N];
 87 void spfa()
 88 {
 89     int x1=gi(),u1=gi(),y1=gi(),u2=gi(),u,x;
 90     for(int i=0;i<=ids;i++)f[i]=INF,vis[i]=false;
 91     int t=0,sum=0;ll dist;
 92     for(int i=0,sz=key[u1].size();i<sz;i++){
 93         u=key[u1][i];
 94         f[u]=query(id[u],x1);
 95         q[++sum]=u;
 96         vis[u]=true;
 97     }
 98     while(t!=sum){
 99         t++;t%=mod;x=q[t];
100         for(int i=head[x];i;i=a[i].next){
101             u=a[i].to;
102             if(f[x]+1<f[u]){
103                 f[u]=f[x]+1;
104                 if(vt[vis[u]])vt[vis[u]]=false;
105                 if(!vis[u])sum++,sum%=mod,q[sum]=u,vis[u]=sum,vt[sum]=false;
106             }
107         }
108         if(!vt[vis[x]])
109         for(int i=0,sz=key[bel[x]].size();i<sz;i++){
110             u=key[bel[x]][i];
111             if(u==x)continue;
112             dist=query(id[u],id[x]);
113             if(f[x]+dist<f[u]){
114                 f[u]=f[x]+dist;
115                 if(!vis[u])sum++,sum%=mod,q[sum]=u,vis[u]=sum,vt[sum]=true;
116             }
117         }
118         vis[x]=0;
119     }
120     ll ans=2e15;
121     for(int i=0,sz=key[u2].size();i<sz;i++){
122         u=key[u2][i];
123         dist=query(id[u],y1);
124         if(f[u]+dist<ans)ans=f[u]+dist;
125     }
126     if(u1==u2)ans=min(ans,(ll)query(x1,y1));
127     if(ans!=2e15)printf("%lld\n",ans);
128     else printf("impossible\n");
129 }
130 int main()
131 {
132     freopen("m.in","r",stdin);
133     freopen("m.out","w",stdout);
134     n=gi();m=gi();Q=gi();
135     int x,y;
136     for(int i=1;i<n;i++){
137         x=gi();y=gi();
138         t[x].push_back(y);t[y].push_back(x);
139     }
140     dep[1]=1;
141     dfs1(1);dfs2(1,1);
142     int u1,u2,xx,yy;
143     for(int i=1;i<=m;i++){
144         x=gi();u1=gi();y=gi();u2=gi();
145         xx=find(u1,x);yy=find(u2,y);
146         if(!xx)xx=++ids,key[u1].push_back(ids),bel[ids]=u1,id[ids]=x,adds(u1,x,ids);
147         if(!yy)yy=++ids,key[u2].push_back(ids),bel[ids]=u2,id[ids]=y,adds(u2,y,ids);
148         addedge(xx,yy);
149     }
150     while(Q--)spfa();
151     return 0;
152 }

 

转载于:https://www.cnblogs.com/Yuzao/p/7138036.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值