[1] eleven exam chain split tree T2

Algorithm thinking not say, in fact, relatively simple

Here to talk about the pit:

1. Although we can press the point on the right side, but when the root is not the same, the difference array is clearly different. So we can not really be seen as the right side of the right point, or right side as you want it to be considered when changing root.
1. Update, we set dp [u] u node represents the maximum value at the time of the root, due after point u, v point son will become a point u, so at this point we have to update the son of maximum v value and the second largest value. note! To update more than the maximum value, the second largest value should be properly maintained

I did not add the code to optimize, because to ensure the correct pretty good

#include<bits/stdc++.h>
using namespace std;

#define go(i,a,b) for(int i=a;i<=b;++i)
#define com(i,a,b) for(int i=a;i>=b;--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define head(x) for(int i=head[x];i+1;i=e[i].nxt)
#define int long long

const int inf=0x3f3f3f3f3f3f3f3f,N=1e5+10,t=17;

int n,m,head[N],cnt,son[N],c[N],dep[N],f[N][20],mx[N],se[N],ans=0,dp[N];

struct edge{
    int nxt,v;
}e[N*2];

void add(int u,int v){
    e[cnt]=(edge){head[u],v};
    head[u]=cnt++;
}

inline void read(int &x){
    x=0;char f=1,c=getchar();
    while(!isdigit(c)){ if(c=='-') f=-1; c=getchar(); }
    while(isdigit(c)){ x=x*10+c-'0'; c=getchar(); }
    x*=f;
}

void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    head(u){
        int v=e[i].v;
        if(v==fa) continue;
        dfs(v,u);
    }
}

int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    com(i,t,0){
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    }
    if(x==y) return x;
    com(i,t,0){
        if(f[x][i]!=f[y][i])
            x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}

void Dfs(int u,int fa){
    head(u){
        int v=e[i].v;
        if(v==fa) continue;
        Dfs(v,u);
        c[u]+=c[v];
    }
}

void DFS(int u,int fa){
    head(u){
        int v=e[i].v;
        if(v==fa) continue;
        DFS(v,u);
        if(c[v]>=mx[u]){
            se[u]=mx[u];
            mx[u]=c[v];
        }
        else if(c[v]>se[u]) se[u]=c[v];
    }
    dp[1]+=mx[u];
}

void DFs(int u,int fa){
    head(u){
        int v=e[i].v;
        if(v==fa) continue;
        dp[v]=dp[u];
        if(mx[u]==c[v]) dp[v]=dp[v]-mx[u]+se[u];
        if(c[v]>=mx[v]){
            dp[v]=dp[v]+c[v]-mx[v];
            se[v]=mx[v];
            mx[v]=c[v];
        }
        else if(c[v]>se[v]) se[v]=c[v];
        DFs(v,u);
    }
}

signed main(){
    mem(head,-1);
    read(n),read(m);
    int u,v,Lca;
    go(i,2,n){
        read(u),read(v);
        add(u,v),add(v,u);
    }
    dfs(1,0);
    go(j,1,t)
        go(i,1,n)
            f[i][j]=f[f[i][j-1]][j-1];
    while(m--){
        read(u),read(v);
        Lca=lca(u,v);
        ++c[u],++c[v];
        c[Lca]-=2;
        ans+=dep[u]+dep[v]-2*dep[Lca];
    }
    Dfs(1,0);
    DFS(1,0);   
    DFs(1,0);
    int tot=ans;
    go(i,1,n)
        ans=min(ans,tot-dp[i]);
    printf("%lld",ans);
    return 0;
}

Guess you like

Origin www.cnblogs.com/White-star/p/11616222.html