DTOJ#5209. 人头一拿我就起飞

马老师打算起飞。

召唤师峡谷有无穷多个位面,每个位面都是一样的 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 n1 行,每行两个数,描述树边。

接下来 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 n1000,m3000,v,q1000

对于另外 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 n300000,m100000,Q10,v,q200000

把航道端点和查询端点拉出跑虚树,在虚树上跑最短路。
注意卡常技巧:
离散化时开 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;
}

猜你喜欢

转载自blog.csdn.net/CSDNzhanghongyu/article/details/110495877