Tarjan_LCA

貌似求LCA使用倍增已经可以应付掉大多数需要LCA的题了..

但是有些时候$O(MlogN)$的复杂度就不可接受了

Tarjan_LCA对于每个询问采用离线处理

总复杂度为$O(M+N)$

这个复杂度几乎不可能被卡掉

简单说的话用Tarjan求LCA就是根据后序dfs的框架然后用并查集加持。

具体实现过程参加代码。

用HDU2586作为模板

//HUD 2586 Tarjan_LCA
//by Cydiater
//2016.8.15
#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <queue>
#include <map>
#include <iomanip>
#include <algorithm>
using namespace std;
#define ll long long
#define up(i,j,n)       for(int i=j;i<=n;i++)
#define down(i,j,n)     for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
const int oo=0x3f3f3f3f;
inline int read(){
      char ch=getchar();int x=0,f=1;
      while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
      while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
      return x*f;
}
int N,M,LINK[MAXN],len=0,dis[MAXN],fa[MAXN],tol=0,Link[MAXN],g[MAXN],T,ans[MAXN];
bool vis[MAXN];
struct edge{int y,next,v;}e[MAXN];
struct query{int y,next,lca;}q[MAXN];
namespace solution{
      inline void insert(int x,int y,int v){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;e[len].v=v;}
      inline void Insert(int x,int y){q[++tol].next=Link[x];Link[x]=tol;q[tol].y=y;}
      int get(int k){
            if(g[k]==k) return k;
            g[k]=get(g[k]);
            return g[k];
      }
      void dfs(int node,int dist,int father){
            fa[node]=father;dis[node]=dist;
            for(int i=LINK[node];i;i=e[i].next)
                  if(e[i].y!=father)
                        dfs(e[i].y,dist+e[i].v,node);
      }
      void init(){
            N=read();M=read();
            up(i,1,N-1){
                  int x=read(),y=read(),v=read();
                  insert(x,y,v);
                  insert(y,x,v);
            }
            memset(fa,0,sizeof(fa));
            memset(dis,0,sizeof(dis));
            memset(vis,0,sizeof(vis));
            dfs(1,0,0);
            up(i,1,M){
                  int x=read(),y=read();
                  Insert(x,y);
            }
      }
      void lca(int node){
            vis[node]=1;g[node]=node;
            for(int i=LINK[node];i;i=e[i].next)
                  if(!vis[e[i].y]){
                        lca(e[i].y);
                        g[e[i].y]=node;
                  }
            for(int i=Link[node];i;i=q[i].next)
                  if(vis[q[i].y]){
                        q[i].lca=get(q[i].y);
                        ans[i]=dis[node]+dis[q[i].y]-2*dis[q[i].lca];
                  }
      }
      void output(){
            up(i,1,M)printf("%d\n",ans[i]);
      }
}
int main(){
      //freopen("input.in","r",stdin);
      using namespace solution;
      T=read();
      while(T--){
            tol=0;len=0;
            memset(Link,0,sizeof(Link));
            memset(LINK,0,sizeof(LINK));
            init();
            lca(1);
            output();
      }
      return 0;
}
上一篇:CE选择目录对话框(转)


下一篇:struts2上传