// node of the tree is 1 based index so if in any problem nodes are
// 0 based than make it 1 based by increasein 1 each node while
// makin graph , also at the time of query increase by 1
// all array euler[1000000],level[1000000],f_occ[1000000] are 0 based index
// seg tree is 1 based index .....
#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
int euler[1000000],level[1000000],f_occ[1000000];
int id=0;
list<int > li[1000000];
int kk=0;
lli dist[1000000];
#define inf 100000000
struct st
{
int val;
int index;
} tree[1000000];
void dfs(int start,int lev,int par)
{
euler[id]=start;
level[id]=lev;
f_occ[start]=min(f_occ[start],id);
id++;
list<int>:: iterator it;
for(it=li[start].begin();it!=li[start].end();it++)
{
if(*it!=par)
{
dfs(*it,lev+1,start);
euler[id]=start;
level[id]=lev;
f_occ[start]=min(f_occ[start],id);
id++;
}
}
}
st query(int node,int start,int end,int r1,int r2)
{
if(start>end || r1>end || r2<start)
{
st ab;
ab.val=inf;
ab.index=-1;
return ab;
}
if(r1<=start && r2>=end)
{
return tree[node];
}
else
{
st q1=query(2*node,start,(start+end)/2,r1,r2);
st q2=query(2*node+1,((start+end)/2)+1,end,r1,r2);
if(q1.val<q2.val) return q1;
else return q2;
}
}
void build(int node , int start,int end)
{
if(start==end)
{
tree[node].val=level[start];
tree[node].index=start;
return ;
}
else if(start>end)
{
tree[node].val=inf;
tree[node].index=-1;
return ;
}
else
{
build(2*node,start,(start+end)/2);
build(2*node+1,((start+end)/2)+1,end);
if(tree[2*node].val<tree[2*node+1].val)
{
tree[node].val=tree[2*node].val;
tree[node].index=tree[2*node].index;
}
else
{
tree[node].val=tree[2*node+1].val;
tree[node].index=tree[2*node+1].index;
}
}
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n-1;i++)
{
int a,b,c;
cin>>a>>b;
li[a].push_back(b);
li[b].push_back(a);
}
for(int i=0;i<=2*n;i++) f_occ[i]=1000000;
dfs(1,1,0);
id--;
build(1,0,id);
int q;
cin>>q;
while(q--)
{
int a,b;
cin>>a>>b;
int x1=f_occ[a];
int x2=f_occ[b];
if(x1>x2) swap(x1,x2);
st lc=query(1,0,id,x1,x2);
int lca=euler[lc.index];
cout<<lca<<endl;
}
}
---------------------------------------------------------binary rais----------------------------------------
// tree is treated as 1 based
// level is also 1 based
#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
list<int>li[1010];
lli dp[1010][30];
int lev[1010];
int dfs(int start,int par,int le)
{
lev[start]=le;
list<int>:: iterator it;
for(it=li[start].begin();it!=li[start].end();it++)
{
if(*it!=par)
{
dp[*it][0]=start;
lev[*it]=le+1;
dfs(*it,start,le+1);
}
}
}
int binary_rais(int a,int b)// return lca of a,b
{
if(lev[a]<lev[b]) swap(a,b);
int lg;
/// maximum jump that can be alloweable to make both a and
// b at same level will be the depth of the node a
for(lg=1;(1<<lg)<=lev[a];lg++);
//
lg--;
// this will make both at same level
// we can write any number as the power of 2
// so by binary raise we can reach to any node
for(int i=lg;i>=0;i--)
{
if(lev[a]-(1<<i)>=lev[b])
{
a=dp[a][i];// moving a upward
}
}
// now a and b are at same level
// cout<<" at same level "<<a<<" "<<b<<endl;
if(a==b) return a;
else
{
for(int i=lg;i>=0;i--)
{
if(dp[a][i]!=-1 && dp[a][i]!=dp[b][i])// moving botha and b up
{
a=dp[a][i];
b=dp[b][i];
}
}
return dp[a][0];
}
}
int main()
{
int t;
cin>>t;
int cas=1;
while(t--)
{
cout<<"Case "<<cas++<<":"<<endl;
for(int i=0;i<1010;i++)li[i].clear();
int n;
cin>>n;
int m ;
cin>>m;// edge
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
li[a].push_back(b);
li[b].push_back(a);
}
memset(dp,-1,sizeof dp);
// we are consedering 1 as the root of all nodes
// so its parent is non so its pow(2,0) the parent is 0;
dp[1][0]=0;
dfs(1,-1,1);
int max_h=20;// or lon(n)
// maximum height
for(int i=1;i<=max_h;i++)
{
for(int j=1;j<=n;j++)
{
if(dp[j][i-1]!=-1)
dp[j][i]=dp[dp[j][i-1]][i-1];//
}
}
int q;
cin>>q;
while(q--)
{
int a,b;
cin>>a>>b;
cout<< binary_rais(a,b)<<endl;
}
}
}
// 0 based than make it 1 based by increasein 1 each node while
// makin graph , also at the time of query increase by 1
// all array euler[1000000],level[1000000],f_occ[1000000] are 0 based index
// seg tree is 1 based index .....
#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
int euler[1000000],level[1000000],f_occ[1000000];
int id=0;
list<int > li[1000000];
int kk=0;
lli dist[1000000];
#define inf 100000000
struct st
{
int val;
int index;
} tree[1000000];
void dfs(int start,int lev,int par)
{
euler[id]=start;
level[id]=lev;
f_occ[start]=min(f_occ[start],id);
id++;
list<int>:: iterator it;
for(it=li[start].begin();it!=li[start].end();it++)
{
if(*it!=par)
{
dfs(*it,lev+1,start);
euler[id]=start;
level[id]=lev;
f_occ[start]=min(f_occ[start],id);
id++;
}
}
}
st query(int node,int start,int end,int r1,int r2)
{
if(start>end || r1>end || r2<start)
{
st ab;
ab.val=inf;
ab.index=-1;
return ab;
}
if(r1<=start && r2>=end)
{
return tree[node];
}
else
{
st q1=query(2*node,start,(start+end)/2,r1,r2);
st q2=query(2*node+1,((start+end)/2)+1,end,r1,r2);
if(q1.val<q2.val) return q1;
else return q2;
}
}
void build(int node , int start,int end)
{
if(start==end)
{
tree[node].val=level[start];
tree[node].index=start;
return ;
}
else if(start>end)
{
tree[node].val=inf;
tree[node].index=-1;
return ;
}
else
{
build(2*node,start,(start+end)/2);
build(2*node+1,((start+end)/2)+1,end);
if(tree[2*node].val<tree[2*node+1].val)
{
tree[node].val=tree[2*node].val;
tree[node].index=tree[2*node].index;
}
else
{
tree[node].val=tree[2*node+1].val;
tree[node].index=tree[2*node+1].index;
}
}
}
int main()
{
int n;
cin>>n;
for(int i=0;i<n-1;i++)
{
int a,b,c;
cin>>a>>b;
li[a].push_back(b);
li[b].push_back(a);
}
for(int i=0;i<=2*n;i++) f_occ[i]=1000000;
dfs(1,1,0);
id--;
build(1,0,id);
int q;
cin>>q;
while(q--)
{
int a,b;
cin>>a>>b;
int x1=f_occ[a];
int x2=f_occ[b];
if(x1>x2) swap(x1,x2);
st lc=query(1,0,id,x1,x2);
int lca=euler[lc.index];
cout<<lca<<endl;
}
}
---------------------------------------------------------binary rais----------------------------------------
// tree is treated as 1 based
// level is also 1 based
#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
list<int>li[1010];
lli dp[1010][30];
int lev[1010];
int dfs(int start,int par,int le)
{
lev[start]=le;
list<int>:: iterator it;
for(it=li[start].begin();it!=li[start].end();it++)
{
if(*it!=par)
{
dp[*it][0]=start;
lev[*it]=le+1;
dfs(*it,start,le+1);
}
}
}
int binary_rais(int a,int b)// return lca of a,b
{
if(lev[a]<lev[b]) swap(a,b);
int lg;
/// maximum jump that can be alloweable to make both a and
// b at same level will be the depth of the node a
for(lg=1;(1<<lg)<=lev[a];lg++);
//
lg--;
// this will make both at same level
// we can write any number as the power of 2
// so by binary raise we can reach to any node
for(int i=lg;i>=0;i--)
{
if(lev[a]-(1<<i)>=lev[b])
{
a=dp[a][i];// moving a upward
}
}
// now a and b are at same level
// cout<<" at same level "<<a<<" "<<b<<endl;
if(a==b) return a;
else
{
for(int i=lg;i>=0;i--)
{
if(dp[a][i]!=-1 && dp[a][i]!=dp[b][i])// moving botha and b up
{
a=dp[a][i];
b=dp[b][i];
}
}
return dp[a][0];
}
}
int main()
{
int t;
cin>>t;
int cas=1;
while(t--)
{
cout<<"Case "<<cas++<<":"<<endl;
for(int i=0;i<1010;i++)li[i].clear();
int n;
cin>>n;
int m ;
cin>>m;// edge
for(int i=1;i<=m;i++)
{
int a,b;
cin>>a>>b;
li[a].push_back(b);
li[b].push_back(a);
}
memset(dp,-1,sizeof dp);
// we are consedering 1 as the root of all nodes
// so its parent is non so its pow(2,0) the parent is 0;
dp[1][0]=0;
dfs(1,-1,1);
int max_h=20;// or lon(n)
// maximum height
for(int i=1;i<=max_h;i++)
{
for(int j=1;j<=n;j++)
{
if(dp[j][i-1]!=-1)
dp[j][i]=dp[dp[j][i-1]][i-1];//
}
}
int q;
cin>>q;
while(q--)
{
int a,b;
cin>>a>>b;
cout<< binary_rais(a,b)<<endl;
}
}
}
No comments:
Post a Comment