bzoj 3910(LCA+并查集)

来源:互联网 发布:关键词优化简易 编辑:程序博客网 时间:2024/05/16 12:16

传送门
题解:两点间路径唯一就是树啊。。。我这都没看出来,可以退竞晒了。。。LCA不用说,每次询问当前起点(起点不断更新)到当前目标点的距离,这个询问操作就涉及到LCA。然后用维护经过的路径,走过的就把一条链都merge到一起,这个正好就用并查集啊!又是一道”一看题解就懂系列“的题。。。╮(╯▽╰)╭
P.S.自己写的LCA就是快╰(°▽°)╯

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long ll;const int MAXN=5e5+4;int n,m,source;int head[MAXN],fa[MAXN],edge=0;struct EDGE {    int v,nxt;}e[MAXN<<1];int f[21][MAXN],dis[MAXN];ll ans=0;inline int read() {    int x=0;char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();    return x;}inline void adde(int u,int v) {    e[edge].nxt=head[u],e[edge].v=v,head[u]=edge++;    e[edge].nxt=head[v],e[edge].v=u,head[v]=edge++;}void dfs(int p,int father) {    for (int i=head[p];~i;i=e[i].nxt) {        int v=e[i].v;        if (v^father) {            f[0][v]=p;            dis[v]=dis[p]+1;            dfs(v,p);        }    }}inline void da() {    for (int j=1;(1<<j)<=n;++j)        for (int i=1;i<=n;++i)            f[j][i]=f[j-1][f[j-1][i]];}inline int lca(int x,int y) {    if (dis[x]<dis[y]) swap(x,y);    int t=dis[x]-dis[y];    for (int i=0;i<=20;++i)        if (t&(1<<i)) x=f[i][x];    if (x==y) return x;    for (int i=20;i>=0;--i)        if (f[i][x]^f[i][y]) x=f[i][x],y=f[i][y];    return f[0][x];}int find(int p) {    return fa[p]==p?p:fa[p]=find(fa[p]);}int main() {//  freopen("bzoj 3910.in","r",stdin);    memset(head,-1,sizeof(head));     n=read(),m=read(),source=read();    for (register int i=1;i<n;++i) {        int u=read(),v=read();        adde(u,v);fa[i]=i;    }    dis[1]=0;fa[n]=n;    dfs(1,0);    da();//init the LCA array    for (register int k=0;k<m;++k) {        int now=read();        if (find(now)==find(source)) continue;        int anc=lca(now,source);        ans+=dis[now]+dis[source]-(dis[anc]<<1);        int t,x=now;        anc=find(anc);        while (find(x)^anc) {            t=find(x),fa[t]=anc,x=f[0][t];        }        x=source;        while (find(x)^anc) {            t=find(x),fa[t]=anc,x=f[0][t];        }        source=now;    }    printf("%lld\n",ans);}
原创粉丝点击