HDU6203 ping ping ping 【LCA+BIT】

傳送門


先求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
:2lcau,vlcau,v=lcau,v(flag>0)
:lcau,v(flag>0)(flag=0)
:2lcau,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];//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;
}
發佈了292 篇原創文章 · 獲贊 82 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章