记录编号 189065 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队 2011] 公交路线 最终得分 100
用户昵称 Gravatar四季木哥 是否通过 通过
代码语言 C++ 运行时间 7.069 s
提交时间 2015-09-25 22:05:40 内存使用 50.81 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#define N 200550
#define INF 0x3f3f3f3f
using namespace std;
int pre[N][22], C[N], dfn[N], end[N], fa[N][22], dep[N], cnt[N], vis[N];
int S[N], T[N], cur, answer[N], num[N];
int n, t, m, _dfn; 
vector<int> G[N];
vector<int> p[N];
vector<int> quest[N*2];
void get(int &x){
	char c = getchar(); x = 0;
	while(c < '0' || c > '9') c = getchar();
	while(c <= '9' && c >= '0') x = x*10+c-48, c = getchar();
}
 
inline int lowbit(int x){
    return x&(-x);
}
 
inline int sum(int x){
    int ret=0;
    while(x>0) {
	    ret+=C[x]; x-=lowbit(x);
	}
	return ret;
}
 
inline void add(int x){
    while(x<=end[1]){
	   C[x]++; x+=lowbit(x);
	}
}
 
void DFS(int x, int depth){
	if(vis[x]) return;
	vis[x]=1;
    int siz=G[x].size();
    dfn[x]=++_dfn;  
	dep[x]=depth;
	if(!siz){
	    end[x]=dfn[x];
	    return;
	}
	int v;
    for(int i=0;i<siz;i++){
        v=G[x][i];
		if(!vis[v]) fa[v][0]=x;
		DFS(v,depth+1); 
	}
	end[x]=++_dfn;
}
 
void get_pre(int x){
	if(!vis[x]) return;
	vis[x]=0;
	int siz=G[x].size();
	for(int i=0;i<siz;i++) get_pre(G[x][i]); 
	if(dfn[pre[x][0]]<dfn[pre[fa[x][0]][0]]) 
    	pre[fa[x][0]][0]=pre[x][0];
}
 
inline void find_fa(void){
    for(int j=1;j<=17;j++)
        for(int i=1;i<=n;i++)
	        fa[i][j]=fa[fa[i][j-1]][j-1];
}
 
inline void move_up(void){
	get_pre(1);
	for(int i=1;i<=n;i++) if(!pre[i][0]) pre[i][0]=i;
	for(int j=1;j<=17;j++){
	    for(int i=1;i<=n;i++){
            pre[i][j]=pre[pre[i][j-1]][j-1];
        }
    }		
}
 
inline int LCA(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
	int i;    
    for(i=0;dep[x]-(1<<i)>=dep[y];i++) 
	    x=fa[x][i]; 
    if(dep[x]>=dep[y]){
        for(int j=i-1;j>=0;j--)
            if(dep[fa[x][j]]>=dep[y])
			     x=fa[x][j];
    }
	for(i=0;fa[x][i]!=fa[y][i];i++){
		x=fa[x][i]; 
	    y=fa[y][i];
	}
    for(int j=i-1;j>=0;j--){
	    if(fa[x][j]!=fa[y][j]){
	        x=fa[x][j];	
		    y=fa[y][j];
		}
	}
	return fa[x][0];
}
 
inline void Add_Point(int x, int y){
    p[dfn[x]].push_back(dfn[y]);
    p[dfn[y]].push_back(dfn[x]);
}
 
inline void Deal_Point(void){
    for(int i=1;i<=cur;i++){
        quest[dfn[S[i]]-1].push_back(-i);
		quest[end[S[i]]].push_back(i); 		   
	}       
    for(int i=0;i<=_dfn;i++){
    	int siz=p[i].size();
		for(int j=0;j<siz;j++) add(p[i][j]);
        siz=quest[i].size();	
	    for(int j=0;j<siz;j++){
		    int k=abs(quest[i][j]);
			int now=sum(end[T[k]])-sum(dfn[T[k]]-1);
			if(quest[i][j]<0) cnt[k]-=now;
			else cnt[k]+=now;   
		}    
	}
	for(int i=1;i<=cur;i++)
	    if(cnt[i]<=0) answer[num[i]]++;
} 
 
inline int Ask(int x,int y,int k){
	int ans=0;
    if(dfn[x]<dfn[y]) swap(x,y);
    if(dfn[x]<=end[y]){
    	 int i;
	     for(i=0;dfn[pre[x][i]]>dfn[y];i++){
	     	 if(x==pre[x][i]) return -1;
	         x=pre[x][i];
	         ans+=(1<<i);
	     }
	     for(int j=i-1;j>=0;j--){
	     	 if(x==pre[x][i]) return -1;
	         if(dfn[pre[x][j]]>dfn[y]){
	          	 x=pre[x][j];
	          	 ans+=(1<<j);
	         }
	     }
	}else{
	     int i;
	     int lca=LCA(x,y);
	     for(i=0;dfn[pre[x][i]]>dfn[lca];i++){
	     	 if(x==pre[x][i]) return -1;
		     x=pre[x][i];
		     ans+=(1<<i);
		 }
	     for(int j=i-1;j>=0;j--){
	     	 if(x==pre[x][0]) return -1;
		     if(dfn[pre[x][j]]>dfn[lca]){
		         x=pre[x][j];
		         ans+=(1<<j);
			 }
		 }
	     for(i=0;dfn[pre[y][i]]>dfn[lca];i++){
	     	 if(y==pre[y][i]) return -1;
		     y=pre[y][i];
		     ans+=(1<<i);
		 }
	     for(int j=i-1;j>=0;j--){
	     	 if(y==pre[y][i]) return -1;
		     if(dfn[pre[y][j]]>dfn[lca]){
			     y=pre[y][j];
			     ans+=(1<<j);
			 }
		 }
		 S[++cur]=x;
		 T[cur]=y;
		 num[cur]=k;
    }
    return ans;
}
 
inline void work(void){
    get(n);get(t);get(m);
	int x, y;    
    for(int i=1;i<n;i++){
	    get(x); get(y);
	    G[x].push_back(y);
	    G[y].push_back(x);
	}
	dfn[0]=INF;end[0]=-INF;fa[1][0]=1;
    DFS(1,1);
    find_fa();
    for(int i=1;i<=t;i++){
	    get(x); get(y);
	    if(dfn[x]<dfn[y]) swap(x,y);
	    if(end[x]<end[y]) {
			if(dfn[pre[x][0]]>dfn[y])
		         pre[x][0]=y;
		} 
		else {
		    int lca=LCA(x,y);
			if(dfn[pre[x][0]]>dfn[lca]) pre[x][0]=lca;
		    if(dfn[pre[y][0]]>dfn[lca]) pre[y][0]=lca;
			Add_Point(x,y);
		}
	}
    move_up();
}
int main(void){
	freopen("nt2011_bus.in","r",stdin);
	freopen("nt2011_bus.out","w",stdout);
    work();
    int x, y;
	for(int i=1;i<=m;i++){
	    get(x); get(y);
	    answer[i]=Ask(x,y,i);
	}
	Deal_Point();
	for(int i=1;i<=m;i++) printf("%d\n",answer[i]);
return 0;
}