马老师打算起飞。
召唤师峡谷有无穷多个位面,每个位面都是一样的 n n n 个点一棵树,并且马老师还开通了 m m m 个航线,每个航线都可以双向的,可以写成两个二元组 ( u , v ) , ( p , q ) (u,v),(p,q) (u,v),(p,q),意思是从第 v v v 个位面的 u u u 号点到 q q q 个位面的 p p p 号点有一条航线。
马老师从走树上的点和航线需要 1 1 1 的代价,现在有 Q Q Q 个询问 ( u , v , p , q ) (u,v,p,q) (u,v,p,q),代表马老师想从第 v v v 个位面的 u u u 号点到 q q q 个位面的 p p p 号点去捡人头,你需要回答最小代价。
输入的第一行有三个整数 n , m , Q n,m,Q n,m,Q 代表位面的点数数量,航线数量,询问数。
接下来 n − 1 n-1 n−1 行,每行两个数,描述树边。
接下来 m m m 行,每行四个数,描述航线。
接下来 Q Q Q 行,每行四个数,描述询问。
对于每个询问输出答案,如果答案不存在,输出 “ i m p o s s i b l e impossible impossible”(不含引号)
样例输入
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
样例输出
3
3
2
对于 30 % 30\% 30% 的数据, n ≤ 1000 , m ≤ 3000 , v , q ≤ 1000 n\leq 1000, m\leq 3000, v,q\leq 1000 n≤1000,m≤3000,v,q≤1000。
对于另外 20 % 20\% 20% 的数据,树形成了一条链。
对于所有数据, n ≤ 300000 , m ≤ 100000 , Q ≤ 10 , v , q ≤ 200000 n\leq 300000, m\leq 100000, Q\leq 10, v,q\leq 200000 n≤300000,m≤100000,Q≤10,v,q≤200000。
把航道端点和查询端点拉出跑虚树,在虚树上跑最短路。
注意卡常技巧:
离散化时开 n n n个 m a p map map,常数比 1 个 m a p map map 小,刚好卡过。
#include<bits/stdc++.h>
#define N 900005
typedef long long ll;
using namespace std;
inline char GET_CHAR ( void )
{
static char buf[1<<23],*p1=buf,*p2=buf;
return p1==p2 && (p2=(p1=buf)+fread(buf,1,1<<23,stdin),p1==p2) ? EOF : *p1++;
}
inline int read ( void )
{
int x=0;char ch;
while ( !isdigit(ch=GET_CHAR()) ) ;
for ( x=ch^48;isdigit(ch=GET_CHAR()); ) x=(x<<1)+(x<<3)+(ch^48);
return x;
}
vector<int> to[N];
map<int, int> h[N];
int st[N][21],T=19,dfs_num,in[N],ou[N],e[22],Lg[N<<2],dep[N];
void dfs(int x,int las){
in[x]=++dfs_num;
st[dfs_num][0]=x;
for(int i=0;i<to[x].size();++i){
int y=to[x][i];
if(y==las)continue;
dep[y]=dep[x]+1;
dfs(y,x);
st[++dfs_num][0]=x;
}
st[++dfs_num][0]=x;
ou[x]=dfs_num;
}
inline int get(int x,int y){
x=in[x],y=ou[y];
if(x>y)swap(x,y);
int k=Lg[y-x+1];
return (dep[st[x][k]]<dep[st[y-e[k]+1][k]])?st[x][k]:st[y-e[k]+1][k];
}
int dt;
vector<int> di[N];int sta[N],top,n,m,Q;
int qu[N],tot,head[N],ver[N<<1],nex[N<<1],edge[N<<1];
struct node{
int id,dfn;
}tmp[N];
bool cmp(node x,node y){
int k1=x.id<0?ou[-x.id]:in[x.id],k2=y.id<0?ou[-y.id]:in[y.id];return k1<k2;}
int pt,b[N];
struct Node{
int u,v,p,q;
}as[N];
ll d[N],po[N];
inline void add(int x,int y,int z){
nex[++tot]=head[x];head[x]=tot;ver[tot]=y;edge[tot]=z;
nex[++tot]=head[y];head[y]=tot;ver[tot]=x;edge[tot]=z;
}
int v[N];
priority_queue<pair<ll, int> > q;
void dij(int s){
for(int i=1;i<=dt;++i)d[i]=(1LL<<60);
memset(v,0,sizeof(v));
while(!q.empty())q.pop();
d[s]=0;q.push(make_pair(0,s));
while(!q.empty()){
int x=q.top().second;q.pop();
if(v[x])continue;
v[x]=1;
for(int i=head[x];i;i=nex[i]){
int y=ver[i];ll w=edge[i];
if(d[y]>d[x]+w){
d[y]=d[x]+w;
q.push(make_pair(-d[y],y));
}
}
}
}
int main(){
n=read(),m=read(),Q=read();
for(int i=1;i<n;++i){
int x=read(),y=read();
to[x].push_back(y);to[y].push_back(x);
}
dep[0]=n;dep[1]=1;e[0]=1;
for(int i=1;i<=T+1;++i)e[i]=e[i-1]<<1;
dfs(1,0);
dep[0]=n;
for(int i=1;i<=T;++i){
for(int j=1;j+e[i]-1<=dfs_num;++j){
st[j][i]=(dep[st[j][i-1]]<dep[st[j+e[i-1]][i-1]])?st[j][i-1]:st[j+e[i-1]][i-1];
}
}
Lg[0]=0;
for(int i=1;i<=dfs_num;++i){
Lg[i]=e[Lg[i-1]+1]<=i?Lg[i-1]+1:Lg[i-1];
}
for(int i=1;i<=m;++i){
int u=read(),v=read(),p=read(),q=read();
if(!h[v].count(u)){
h[v][u]=++dt;}
if(!h[q].count(p)){
h[q][p]=++dt;}
di[v].push_back(u);di[q].push_back(p);
add(h[v][u],h[q][p],1);
}
for(int i=1;i<=Q;++i){
as[i].u=read(),as[i].v=read(),as[i].p=read(),as[i].q=read();
if(!h[as[i].v].count(as[i].u)){
h[as[i].v][as[i].u]=++dt;}
if(!h[as[i].q].count(as[i].p)){
h[as[i].q][as[i].p]=++dt;}
di[as[i].v].push_back(as[i].u);di[as[i].q].push_back(as[i].p);
}
for(int i=1;i<=200000;++i){
if(di[i].size()==0)continue;
pt=0;
sort(di[i].begin(),di[i].end());
di[i].erase(unique(di[i].begin(),di[i].end()),di[i].end());
for(int j=0;j<di[i].size();++j){
tmp[++pt].id=di[i][j];tmp[pt].dfn=in[di[i][j]];
b[di[i][j]]=1;
}
sort(tmp+1,tmp+pt+1,cmp);
for(int j=2;j<=pt;++j){
if(b[tmp[j].id]==2)break;
int x=tmp[j-1].id,y=tmp[j].id;
int lca=get(x,y);
if(b[lca])continue;
b[lca]=2;tmp[++pt].id=lca;tmp[pt].dfn=in[lca];
}
for(int j=1;j<=pt;++j){
if(tmp[j].id<0)break;
tmp[++pt].id=-tmp[j].id;
}
sort(tmp+1,tmp+pt+1,cmp);
top=0;
for(int j=1;j<=pt;++j){
int x=tmp[j].id;
if(x<0){
--top;continue;}
if(!h[i].count(x)){
h[i][x]=++dt;po[dt]=h[i][x];}
if(top)add(h[i][x],h[i][sta[top]],dep[x]-dep[sta[top]]);
sta[++top]=x;
}
for(int j=1;j<=pt;++j){
b[abs(tmp[j].id)]=0;
}
}
for(int i=1;i<=Q;++i){
int x=h[as[i].v][as[i].u],y=h[as[i].q][as[i].p];
dij(x);
if(d[y]==(1LL<<60))puts("impossible");
else printf("%lld\n",d[y]);
}
return 0;
}