POJ-3417: Network LCA + tree difference

analysis

We can try to record how many main edges each additional edge can cover. In this way, we cut off one main edge, and one additional edge can be
checked and maintained on the tree. The weight of the two nodes is +1, LCA's The weight is -2, and finally judge whether it is covered by the only one

Code

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;

const int N = 4e5 + 10,M = N * 2;
int h[N],ne[M],e[M],idx;
int d[N],f[N][16];
int n,m;
int w[N];

void add(int a,int b){
    
    
    ne[idx] = h[a],e[idx] = b,h[a] = idx++;
}

void bfs(int root){
    
    
    memset(d,0x3f,sizeof d);
    d[0] = 0,d[root] = 1;
    queue<int> Q;
    Q.push(root);
    while(Q.size()){
    
    
        int t = Q.front();
        Q.pop();
        for(int i = h[t];~i;i = ne[i]){
    
    
            int j = e[i];
            if(d[j] > d[t] + 1){
    
    
                d[j] = d[t] + 1;
                Q.push(j);
                f[j][0] = t;
                for(int k = 1;k <= 15;k++)
                    f[j][k] = f[f[j][k - 1]][k - 1];
            }
        }
    }
}

void dfs(int x,int fa){
    
    
    for(int i = h[x];~i;i = ne[i]){
    
    
        int j = e[i];
        if(j == fa) continue;
        dfs(j,x);
        w[x] += w[j];
    }
}

int LCA(int a,int b){
    
    
    if(d[a] < d[b]) swap(a,b);
    for(int i = 15;i >= 0;i--)
        if(d[f[a][i]] >= d[b])
            a = f[a][i];
    if(a == b) return a;
    for(int i = 15;i >= 0;i--)
        if(f[a][i] != f[b][i])
            a = f[a][i],b = f[b][i];
    return f[a][0];
}

int main(){
    
    
    memset(h,-1,sizeof h);
    scanf("%d%d",&n,&m);
    for(int i = 1;i < n;i++){
    
    
        int a,b;
        scanf("%d%d",&a,&b);
        add(a,b),add(b,a);
    }
    bfs(1);
    for(int i = 1;i <= m;i++){
    
    
        int a,b;
        scanf("%d%d",&a,&b);
        int c = LCA(a,b);
        w[a]++,w[b]++,w[c] -= 2;
    }
    dfs(1,0);
    int res = 0;
    for(int i = 2;i <= n;i++){
    
    
        if(!w[i]) res += m;
        if(w[i] == 1) res++;
    }
    printf("%d\n",w[1]);
}


Guess you like

Origin blog.csdn.net/tlyzxc/article/details/115169899