貌似求LCA使用倍增已经可以应付掉大多数需要LCA的题了..
但是有些时候O(MlogN)的复杂度就不可接受了
Tarjan_LCA对于每个询问采用离线处理
总复杂度为O(M+N)
这个复杂度几乎不可能被卡掉
简单说的话用Tarjan求LCA就是根据后序dfs的框架然后用并查集加持。
具体实现过程参加代码。
用HUD2586作为模板
1 //HUD 2586 Tarjan_LCA 2 //by Cydiater 3 //2016.8.15 4 #include <iostream> 5 #include <cstring> 6 #include <string> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cmath> 10 #include <ctime> 11 #include <queue> 12 #include <map> 13 #include <iomanip> 14 #include <algorithm> 15 using namespace std; 16 #define ll long long 17 #define up(i,j,n) for(int i=j;i<=n;i++) 18 #define down(i,j,n) for(int i=j;i>=n;i--) 19 const int MAXN=1e6+5; 20 const int oo=0x3f3f3f3f; 21 inline int read(){ 22 char ch=getchar();int x=0,f=1; 23 while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();} 24 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();} 25 return x*f; 26 } 27 int N,M,LINK[MAXN],len=0,dis[MAXN],fa[MAXN],tol=0,Link[MAXN],g[MAXN],T,ans[MAXN]; 28 bool vis[MAXN]; 29 struct edge{int y,next,v;}e[MAXN]; 30 struct query{int y,next,lca;}q[MAXN]; 31 namespace solution{ 32 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;} 33 inline void Insert(int x,int y){q[++tol].next=Link[x];Link[x]=tol;q[tol].y=y;} 34 int get(int k){ 35 if(g[k]==k) return k; 36 g[k]=get(g[k]); 37 return g[k]; 38 } 39 void dfs(int node,int dist,int father){ 40 fa[node]=father;dis[node]=dist; 41 for(int i=LINK[node];i;i=e[i].next) 42 if(e[i].y!=father) 43 dfs(e[i].y,dist+e[i].v,node); 44 } 45 void init(){ 46 N=read();M=read(); 47 up(i,1,N-1){ 48 int x=read(),y=read(),v=read(); 49 insert(x,y,v); 50 insert(y,x,v); 51 } 52 memset(fa,0,sizeof(fa)); 53 memset(dis,0,sizeof(dis)); 54 memset(vis,0,sizeof(vis)); 55 dfs(1,0,0); 56 up(i,1,M){ 57 int x=read(),y=read(); 58 Insert(x,y); 59 } 60 } 61 void lca(int node){ 62 vis[node]=1;g[node]=node; 63 for(int i=LINK[node];i;i=e[i].next) 64 if(!vis[e[i].y]){ 65 lca(e[i].y); 66 g[e[i].y]=node; 67 } 68 for(int i=Link[node];i;i=q[i].next) 69 if(vis[q[i].y]){ 70 q[i].lca=get(q[i].y); 71 ans[i]=dis[node]+dis[q[i].y]-2*dis[q[i].lca]; 72 } 73 } 74 void output(){ 75 up(i,1,M)printf("%d\n",ans[i]); 76 } 77 } 78 int main(){ 79 //freopen("input.in","r",stdin); 80 using namespace solution; 81 T=read(); 82 while(T--){ 83 tol=0;len=0; 84 memset(Link,0,sizeof(Link)); 85 memset(LINK,0,sizeof(LINK)); 86 init(); 87 lca(1); 88 output(); 89 } 90 return 0; 91 }
时间: 2024-11-26 01:32:54