准备:
1.C++的几种for循环遍历:5种、Range-based for loops,其中auto在C++11标准的语法中,auto被定义为自动推断变量的类型,不过C++11的auto关键字时有一个限定条件,那就是必须给申明的变量赋予一个初始值,否则编译器在编译阶段将会报错。
2.存储数据:
typedef pair<int,int> pii;
const int N = 1e5 + 5;
vector<pii> G[N];// u的邻接表(first为相邻节点,second为边权)
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 1; i < n; i++) {
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
G[u].push_back(pii(v, w));
G[v].push_back(pii(u, w));
}
两个点的lca跟树根好像没有关系
倍增法:
void dfs(int u, int fa) {
p[u][0] = fa;
for(int i = 1; i < LOG; i++) {
p[u][i] = p[p[u][i-1]][i-1];
}
for(int v : G[u]) {
if(v == fa) continue;
dep[v] = dep[u] + 1;
dfs(v, u);
}
}
int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
for(int i = 0; i < LOG; i++) {
if((dep[u] - dep[v])>>i&1) u = p[u][i];
}
if(u == v) return u;
for(int i = LOG-1; ~i; i--) {
if(p[u][i] != p[v][i]) {
u = p[u][i];
v = p[v][i];
}
}
return p[u][0];
}
参考答案:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 10e4+10;
const int LOG = 18;
int dep[N],p[N][LOG];
vector<int> G[N];
void dfs(int u,int fa)
{
for(int i = 1;i < LOG;i ++)
{
p[u][i] = p[p[u][i-1]][i-1];
}
for(int v = 0;v < G[u].size();v ++)
{
if(G[u][v] == fa) continue;
dep[G[u][v]] = dep[u] + 1;
dfs(G[u][v],u);
}
}
int lca(int u,int v)
{
if(dep[u] < dep[v]) swap(u,v);
for(int i = 0;i < LOG;i ++)
if((dep[u]-dep[v])>>i & 1) u = p[u][i];
if(u == v) return u;
for(int i = LOG -1;~i;i --)
{
if(p[u][i] != p[v][i])
{
u = p[u][i];
v = p[v][i];
}
}
return p[u][0];
}
int main()
{
int T,n;
scanf("%d",&T);
while(T --)
{
scanf("%d",&n);
int u,v;
for(int i = 1;i <= n;i ++)
{
G[i].clear();
memset(p[i],0,sizeof(p[i]));
}
memset(dep,0,sizeof(dep));
for(int i = 1;i < n;i ++)
{
scanf("%d %d",&u,&v);
G[u].push_back(v);
p[v][0] = u;
}
for(int i = 1;i < n;i ++)
if(p[i][0] == 0)
{
dfs(i,0);
break;
}
scanf("%d %d",&u,&v);
printf("%d\n",lca(u,v));
}
return 0;
}
题目:
How far away
参考答案:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<vector>
using namespace std;
const int N = 10e4 * 4 + 2;
const int LOG = 16;
vector<pair<int,int>> G[N];
int dep[N],dis[N],p[N][LOG];
void dfs(int u,int fa)
{
for(int i = 1;i < LOG;i ++)
{
p[u][i] = p[p[u][i-1]][i-1];
}
for(int e = 0;e < G[u].size();e ++)
{
int v = G[u][e].first,w = G[u][e].second;
if(v == fa) continue;
dep[v] = dep[u] + 1;
dis[v] = dis[u] + w;
p[v][0] = u;
dfs(v,u);
}
}
int lca(int u,int v)
{
if(dep[u] < dep[v]) swap(u,v);
for(int i = 0;i < LOG;i ++)
if((dep[u]-dep[v]) >> i & 1)
u = p[u][i];
if(u == v) return u;
for(int i = LOG-1;~ i;i --)
{
if(p[u][i] != p[v][i])
{
u = p[u][i];
v = p[v][i];
}
}
return p[u][0];
}
int main()
{
int t,n,m;
scanf("%d",&t);
while(t --)
{
scanf("%d %d",&n,&m);
int u,v,w;
for(int i = 0;i < n;i ++)
G[i].clear();
for(int i = 1;i < n;i ++)
{
scanf("%d %d %d",&u,&v,&w);
G[u].push_back(pair<int,int>(v,w));
G[v].push_back(pair<int,int>(u,w));
}
dep[1] = 1;
dfs(1,0);
while(m --)
{
scanf("%d %d",&u,&v);
printf("%d\n",dis[u]+dis[v]-2*dis[lca(u,v)]);
}
}
return 0;
}