先求dfs序in[]和out[],以及lca
將不能連通的(u,v)按lca深度從大到小排序
樹狀數組維護數組flag[]
依次處理每對(u,v)
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=1e9+7;
const int INF = inf;
const int N = 1e4 + 5;//頂點數
const int M = 50000 + 5;//查詢數
struct Query{
int u,v,lca;
};
vector<int>G[N];//fist:to second:w邊權
vector<pii>queryTo[N];//first:to second:這個查詢在query[M]中的下標
Query query[M];
int par[N];//並查集
bool visited[N];//Tarjan標記是否被訪問過
inline int find(int x){
return x==par[x]?x:par[x]=find(par[x]);
}
void Tarjan(int u){
visited[u]=true;
for(int i=0;i<G[u].size();++i){
int to=G[u][i];
if(visited[to]==false){
Tarjan(to);
par[to]=u;
}
}
for(int i=0;i<queryTo[u].size();++i){
int v=queryTo[u][i].first;
int index=queryTo[u][i].second;
if(visited[v])
query[index].lca=find(v);
}
}
void init(int n){
fill(visited,visited+n+1,0);
for(int i=0;i<=n;++i){
par[i]=i;
}
}
int in[N],out[N],depth[N];
void dfs(int u,int &t,int fa,int d){
in[u]=++t;
depth[u]=d;
for(int v:G[u]){
if(v!=fa){
dfs(v,t,u,d+1);
}
}
out[u]=t;
}
struct Bit{
int c[N],n;
void init(int n){
this->n=n+1;
fill(c,c+n+2,0);
}
void add(int x,int val){//a[x]...a[n] 全部+val
x+=1;
while(x<=n){
c[x]+=val;
x+=lowbit(x);
}
}
ll sum(int x){//a[x]
ll ans=0;
x+=1;
while(x){
ans+=c[x];
x-=lowbit(x);
}
return ans;
}
}bit;
bool operator>(const Query&a,const Query&b){
return depth[a.lca]>depth[b.lca];
}
int slove(int n,int q){
init(n);
{
int t=-1;
dfs(0,t,-1,0);
}
bit.init(n);
Tarjan(0);
sort(query,query+q,greater<Query>());
int ans=0;
for(int i=0;i<q;++i){
Query&t=query[i];
if(bit.sum(in[t.u])||bit.sum(in[t.v])){
continue;
}
++ans;
int st=in[t.lca],ed=out[t.lca];
bit.add(st,1);
bit.add(ed+1,-1);
}
return ans;
}
int main(){
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int n;
while(~scanf("%d",&n)){
for(int i=0;i<=n;++i){
G[i].clear();
queryTo[i].clear();
}
for(int i=1;i<=n;++i){
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
int p;
scanf("%d",&p);
for(int i=0;i<p;++i){
int u,v;
scanf("%d%d",&u,&v);
query[i]={u,v,-1};
queryTo[u].push_back({v,i});
queryTo[v].push_back({u,i});
}
printf("%d\n",slove(n,p));
}
return 0;
}