傳送門
先求dfs序in[]和out[],以及lca
將不能連通的(u,v)按lca深度從大到小排序
樹狀數組維護數組flag[]
flag[ini]=0:i點與任意{v|flag[inv]=0}連通
flag[ini]>0:i點與任意{v|flag[inv]=0}不連通
依次處理每對(u,v)
若flag[inu]>0||flag[inv]>0,則u,v已經不連通,跳過
否則,將lcau,v視為壞點,將flag[inlca...outlca]全都+1
因為當前取出的(u,v),lcau,v深度比之前的都小,所以要么flag[inu]=flag[inv]=0,要么一個=0,一個>0
而以后取出的(u′,v′),其中一點的深度必然>=lcau,v深度,所以(u′,v′)的位置只能有3種情況
①:2點都在lcau,v為根的子樹內,且lcau′,v′=lcau,v(flag>0)
②:一點在lcau,v為根的子樹內(flag>0),一點不在(flag=0)
③:2點都不在lcau,v為根的子樹內(flag=0)
所以當u點被確定為壞點,u為根的子樹內的點,與之后查詢的點都不連通,flag[inu]>0
#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];
vector<pii>queryTo[N];
Query query[M];
int par[N];
bool visited[N];
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){x+=
1;
while(x<=n){c[x]+=val;x+=lowbit(x);}}ll sum(
int 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(){
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;
}
總結
以上是生活随笔為你收集整理的HDU6203 ping ping ping 【LCA+BIT】的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。