HDU 2586:How far away ?
程序员文章站
2022-03-23 14:02:07
...
题目很简单,可以用很多方法写
本人只是想练习一下两种求LCA的方法
基于RMQ思想的LCA
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=40000+100;
struct Edge{
int from,to;
int len;
int next;
}edge[maxn*2];
int head[maxn],tot;
int first[maxn],dfs_c[maxn*2],dep_c[maxn*2],dfs_cc;
int dis[maxn];
int n,m;
int fa[maxn*2][20];
int kaven[20];
inline void AddEdge(int u,int v,int len){
edge[tot].from=u;
edge[tot].to=v;
edge[tot].len=len;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].from=v;
edge[tot].to=u;
edge[tot].len=len;
edge[tot].next=head[v];
head[v]=tot++;
}
inline void dfs(int u,int f,int d,int l){
first[u]=++dfs_cc;
dfs_c[dfs_cc]=u;
dep_c[dfs_cc]=d;
dis[u]=l;
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
int v=e.to;
if(v==f) continue;
dfs(v,u,d+1,l+e.len);
dfs_c[++dfs_cc]=u;
dep_c[dfs_cc]=d;
}
}
inline void RMQ(){
for(int i=1;i<=dfs_cc;i++) fa[i][0]=i;
for(int i=1;(1<<i)<=dfs_cc;i++){
for(int j=1;j+(1<<i)-1<=dfs_cc;j++){
int l=fa[j][i-1];
int r=fa[j+(1<<(i-1))][i-1];
if(dep_c[l]<dep_c[r]) fa[j][i]=l;
else fa[j][i]=r;
}
}
}
inline int getLca(int u,int v){
u=first[u];
v=first[v];
if(u>v) swap(u,v);
int len=v-u;
int i;
for(i=0;i<20;i++) if(kaven[i+1]>=len) break;
int l=fa[u][i];
int r=fa[u+(1<<i)][i];
if(dep_c[l]<dep_c[r]) return dfs_c[l];
return dfs_c[r];
}
inline void init(){
tot=dfs_cc=0;
for(int i=1;i<=n;i++) head[i]=-1;
}
inline void scan_d(int &res){
res=0;
char ch;
ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') res=res*10+(ch-'0'),ch=getchar();
}
inline void print_d(int res){
if(res>9) print_d(res/10);
putchar(res%10+'0');
}
int main(){
for(int i=0;i<20;i++) kaven[i]=1<<i;
int T;
scan_d(T);
while(T--){
scan_d(n);
scan_d(m);
init();
for(int i=1;i<n;i++){
int u,v,len;
scan_d(u);
scan_d(v);
scan_d(len);
AddEdge(u,v,len);
}
dfs(1,-1,1,0);
RMQ();
for(int i=1;i<=m;i++){
int u,v;
scan_d(u);
scan_d(v);
int lca=getLca(u,v);
int len=dis[u]+dis[v]-2*dis[lca];
printf("%d\n",len);
}
}
}
tarjan求LCA
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=40000+100;
struct Edge{
int from,to;
int len;
int next;
}edge[maxn*2];
int head[maxn],tot;
struct Query{
int u,v;
int lca;
int next;
}query[maxn*2];
int head_q[maxn],toq;
int dis[maxn];
int n,m;
int fa[maxn];
bool vis[maxn];
inline void AddEdge_q(int u,int v){
query[toq].u=u;
query[toq].v=v;
query[toq].lca=-1;
query[toq].next=head_q[u];
head_q[u]=toq++;
query[toq].u=v;
query[toq].v=u;
query[toq].lca=-1;
query[toq].next=head_q[v];
head_q[v]=toq++;
}
inline void AddEdge(int u,int v,int len){
edge[tot].from=u;
edge[tot].to=v;
edge[tot].len=len;
edge[tot].next=head[u];
head[u]=tot++;
edge[tot].from=v;
edge[tot].to=u;
edge[tot].len=len;
edge[tot].next=head[v];
head[v]=tot++;
}
inline int Find(int x){
if(x!=fa[x]) fa[x]=Find(fa[x]);
return fa[x];
}
inline void dfs(int u,int l){
vis[u]=true;
dis[u]=l;
for(int i=head[u];i!=-1;i=edge[i].next){
Edge e=edge[i];
int v=e.to;
if(vis[v]) continue;
dfs(v,l+e.len);
fa[v]=u;
}
for(int i=head_q[u];i!=-1;i=query[i].next){
Query q=query[i];
int v=q.v;
if(vis[v]){
query[i].lca=query[i^1].lca=Find(v);
}
}
}
inline void init(){
tot=toq=0;
for(int i=1;i<=n;i++) head[i]=head_q[i]=-1,fa[i]=i,vis[i]=false;
}
inline void scan_d(int &res){
res=0;
char ch;
ch=getchar();
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') res=res*10+(ch-'0'),ch=getchar();
}
inline void print_d(int res){
if(res>9) print_d(res/10);
putchar(res%10+'0');
}
int main(){
int T;
scan_d(T);
while(T--){
scan_d(n);
scan_d(m);
init();
for(int i=1;i<n;i++){
int u,v,len;
scan_d(u);
scan_d(v);
scan_d(len);
AddEdge(u,v,len);
}
for(int i=1;i<=m;i++){
int u,v;
scan_d(u);
scan_d(v);
AddEdge_q(u,v);
}
dfs(1,0);
for(int i=1;i<=m;i++){
int j=2*(i-1); // 或者 j = 2*i-1
int u=query[j].u;
int v=query[j].v;
int lca=query[j].lca;
int len=dis[u]+dis[v]-2*dis[lca];
printf("%d\n",len);
}
}
}
上一篇: python实现装饰器、描述符
下一篇: 简化版Vector实现