您的位置:首页 > 其它

hdu 4547 (LCA 倍增法)

2014-01-22 15:46 106 查看
中文题就不解释了。

简单LCA,就是求第一个点到LCA的距离,在判断第二个点是不是LCA,不是答案再加一就可。至于求距离的话直接利用倍增法的parent数组拆成二进制复杂度为logn。

代码如下:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#define MP(a, b) make_pair(a, b)
#define PB(a) push_back(a)

using namespace std;

typedef long long ll;
typedef pair<int ,int> pii;
typedef pair<unsigned int, unsigned int> puu;
typedef pair<int ,double> pid;
typedef pair<ll, int> pli;

const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int LEN = 100010;
const int LOG_LEN = 22;
vector<int> Map[LEN];
map<string, int> mp;
int ind[LEN], n ,m, root, depth[LEN], parent[LOG_LEN][LEN];

void dfs(int v, int p, int d){
parent[0][v] = p;
depth[v] = d;
for(int i=0; i<Map[v].size(); i++){
if(Map[v][i]!=p) dfs(Map[v][i], v, d+1);
}
}

void init(int n)
{
dfs(root, -1, 0);
for(int k=0; k+1<LOG_LEN; k++){
for(int i=0; i<n; i++){
if(parent[k][i]<0) parent[k+1][i] = -1;
else parent[k+1][i] = parent[k][parent[k][i]];
}
}
}

int lca(int u, int v)
{
int ret = 0;
if(depth[u]>depth[v])swap(u, v);
for(int k=0; k<LOG_LEN; k++){
if((depth[v]-depth[u]) >> k & 1) v = parent[k][v];
}
if(u==v) return u;
for(int k=LOG_LEN-1; k>=0; k--){
if(parent[k][u]!=parent[k][v]){
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][v];
}

int solve(int v, int p){
int ret = 0;
for(int i=LOG_LEN-1; i>=0; i--)
if(parent[i][v]!=-1 && depth[parent[i][v]]>=depth[p]){
v = parent[i][v];
ret+=(1<<i);
}
return ret;
}

int main()
{
//    freopen("in.txt", "r", stdin);

int T, a, b;
char va[110], vb[110];
scanf("%d", &T);
while(T--){
for(int i=0; i<LEN; i++)Map[i].clear();
mp.clear();
memset(ind, 0, sizeof ind);
scanf("%d%d", &n, &m);
int vcnt = 0;
for(int i=0; i<n-1; i++){
scanf("%s%s", va, vb);
if(!mp.count(va)) mp[va] = vcnt++;
if(!mp.count(vb)) mp[vb] = vcnt++;
ind[mp[va]] ++;
Map[mp[va]].PB(mp[vb]);
Map[mp[vb]].PB(mp[va]);
}
for(int i=0; i<n; i++)if(!ind[i]){root = i;break;}
init(n);
for(int i=0; i<m; i++){
scanf("%s%s", va, vb);
int lv = lca(mp[va], mp[vb]);
printf("%d\n", solve(mp[va], lv)+(lv==mp[vb]?0:1));
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: