tarjan解决LCA

tarjan他老人家比较nbbbb(破音),所以实际上有好几个tarjan算法,这里是解决树上最近公共祖先lca的算法

推荐下一个b站视频,emmm有些长,建议2倍速看

tarjan是离线算法,也就是多个提问只能先存起来,然后一次性解决后输出,不能做到即问即答

具体思想是dfs+并查集

因为dfs的时候,一定会经过两点的lca,具体画个图就很清楚,所以在dfs的时候,对于当前点u看是否有关于它的提问

如果有,那么是否已经访问过它的一个点了,如果访问过,那么Find(已访问过的点)就是这个询问的lca

 

题目是洛谷p3379,裸的板子

 

所以代码(不开o2会超时,e小声)

#include 
using namespace std;
typedef long long ll;
const int maxn = 5e5+7;
vector G[maxn],Q[maxn];
int ans[maxn][3],p[maxn],n,m,s,x,y;
bool vis[maxn];
void init(){for(int i=0;i

 

o2会超时,这你能忍?

链式前向星优化、(笑)

#include 
using namespace std;
typedef long long ll;
const int maxn = 5e5+7;
struct node{int val,next;}E[maxn<<2];
int x,y,n,m,s,tot = 1,ans[maxn][3],p[maxn],Q[maxn],head[maxn];
bool vis[maxn];
void init(){for(int i=0;i edge
    if(flag)E[tot] = {v,Q[u]},Q[u] = tot++;
    else E[tot] = {v,head[u]},head[u] = tot++;
}
int Find(int x){return x == p[x] ? x:p[x] = Find(p[x]);}
void tarjan(int u){
    vis[u] = true;
    for(int v=Q[u];v;v = E[v].next){
        int i = E[v].val;
        if((ans[i][0] == u && vis[ans[i][1]]) || (ans[i][1] == u && vis[ans[i][0]]))
            ans[i][2] = Find(ans[i][0] == u?ans[i][1]:ans[i][0]);
    }
    for(int i=head[u];i;i = E[i].next){
        int v = E[i].val;
        if(vis[v])continue;
        tarjan(v);
        p[v] = u;
    }
}
signed main(){
    init();
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i

压行代码 ( 笑、写着玩的

#include 
using namespace std;
typedef long long ll;
const int maxn = 5e5+7;
int ans[maxn][3],head[2][maxn],Fa[maxn],n,m,s,tot = 1;
bool vis[maxn];
pair E[maxn<<2];
void add(int u,int v,int flag){E[tot] = make_pair(v,head[flag][u]),head[flag][u] = tot++;}
int Find(int x){return x == Fa[x] ? x:Fa[x] = Find(Fa[x]);}
void init(){for(int i=0;i

 

你可能感兴趣的:(模板类(什么,这也是模板))