暗牧 (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 }