HUD-2586(LCA板子)

我就想存个板子而已

倍增法:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
struct Edge
{
    int to;
    int d;
    int next;
}edge[maxn*2];
int head [maxn],tot,in[maxn];
void addedge(int u,int v,int w)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].d=w;
    head[u]=tot++;
}
void init ()
{
    tot=0;
    memset(in,0,sizeof(in));
    memset(head,-1,sizeof(head));
}
int fa[maxn][30];
int deg[maxn],d[maxn];
void BFS(int root)
{
    queue <int > que;
    deg[root]=d[root]=0;
    fa[root][0]=root;
    que.push(root);
    while(!que.empty())
    {
        int tmp=que.front();
        que.pop();
        for(int i=1;i<30;i++)
            fa[tmp][i]=fa[fa[tmp][i-1]][i-1];
        for(int i=head[tmp];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(v==fa[tmp][0])continue;
            deg[v]=deg[tmp]+1;
            d[v]=d[tmp]+edge[i].d;
            fa[v][0]=tmp;
            que.push(v);
        }
    }
}
int LCA (int u,int v)
{
    if(deg[u]>deg[v])swap(u,v);
    int hu=deg[u],hv=deg[v];
    int tu=u,tv=v;
    for(int det=hv-hu,i=0;det;det>>=1,i++)
    {
        if(det&1)
            tv=fa[tv][i];
    }
    if(tu==tv)return tu;
    for(int i=30-1;i>=0;i--)
    {
        if(fa[tu][v]==fa[tv][i])continue;
        tu=fa[tu][i];
        tv=fa[tv][i];
    }
    return fa[tu][0];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        init();
        for(int i=0;i<n-1;i++)
        {
            int u,v,val;
            scanf("%d%d%d",&u,&v,&val);
            addedge(u,v,val);
            addedge(v,u,val);
            in[v]=1;
        }
        int tt;
        for(int i=1;i<=n;i++)
        {
            if(!in[i]){tt=i;break;}
        }
        BFS(tt);
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            printf("%d
",d[u]+d[v]-2*d[LCA(u,v)]);
        }
    }
}

Tarjan:

#include<bits/stdc++.h>
using namespace std;
const int N=40000+100;
int head[N];
int vis[N];
int parent[N];
int ans[N];
int cnt;
vector<int>q[N];
vector<int>Q[N];
int dis[N];
int n;
int ancestor[N];
struct node{
    int to,next,w;
}edge[2*N+10];
void init(){
    cnt=0;
    memset(ans,0,sizeof(ans));
    memset(dis,0,sizeof(dis));
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    for(int i=0;i<=n;i++){
        parent[i]=i;
        Q[i].clear();
        q[i].clear();
    }
}
void add(int u,int v,int w){
    edge[cnt].to=v;
    edge[cnt].w=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int find(int x){
    int r=x;
    while(r!=parent[x])r=parent[r];
    int i=x;
    int j;
    while(parent[i]!=r){
        j=parent[i];
        parent[i]=r;
        i=j;
    }
    return r;
}
void Union(int x,int y){
    x=find(x);
    y=find(y);
    if(x!=y)parent[y]=x;
}
void Tarjan(int x,int w){
    vis[x]=1;
    dis[x]=w;
    //cout<<dis[x]<<endl;
    for(int i=head[x];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(vis[v])continue;
        Tarjan(v,w+edge[i].w);
        Union(x,v);
        ancestor[find(x)]=x;
    }
    for(int i=0;i<q[x].size();i++){
        int u=q[x][i];
        if(vis[u]){
            int t=ancestor[find(u)];
            ans[Q[x][i]]=dis[x]+dis[u]-dis[t]*2;
        }
    }
}
int main(){
    int m;
    int t;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        int u,v,w;
        for(int i=0;i<n-1;i++){
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);
            add(v,u,w);
        }
        for(int i=0;i<m;i++){
            scanf("%d%d",&u,&v);
            q[u].push_back(v);
            q[v].push_back(u);
            Q[u].push_back(i);
            Q[v].push_back(i);
        }
        Tarjan(1,0);
       // for(int i=1;i<=n;i++)cout<<dis[i]<<" ";
        //cout<<endl;
        for(int i=0;i<m;i++){
               // cout<<4<<endl;
            cout<<ans[i]<<endl;
        }
    }
}
原文地址:https://www.cnblogs.com/kayiko/p/12126300.html