|
以前没见过“最近公共祖先”这一类的题啊。长见识了,呵呵。 解法基本上就是 http://www.cppblog.com/varg-vikernes/archive/2010/03/10/109355.html 这篇文章里面提到的两种方法。 两种方法的解法都非常精妙! 最后程序写出来: Tarjan 3372K 219MS DFS+RMQ 7992K 329MS
代码 Tarjan:
#include <stdio.h>

#define MAX_N 40032
#define MAX_Q 10032

 struct edge_node {
struct edge_node *next;
int idx, len;
};
struct edge_node edges[MAX_N*2];

 struct tree_node {
struct edge_node *edge;
struct query_node *query;
int depth, visited;
};
struct tree_node tree[MAX_N];

 struct query_node {
int idx, ans;
struct query_node *next;
};
struct query_node queries[MAX_Q*2];

 struct set_node {
int parent, len;
};
struct set_node set[MAX_N];

__inline int max(int a, int b)
  {
return a > b ? a : b;
}

__inline int find(int idx)
  {
static int stack[MAX_N];
int i, sp;

 for (sp = 0; set[idx].parent; sp++) {
stack[sp] = idx;
idx = set[idx].parent;
}
 for (sp--; sp >= 0; sp--) {
i = stack[sp];
set[i].len += set[set[i].parent].len;
set[i].parent = idx;
}
return idx;
}

__inline void add_edge(int idx, int a, int b, int len)
  {
struct edge_node *p = &edges[idx];
p->idx = b;
p->len = len;
p->next = tree[a].edge;
tree[a].edge = p;
}

__inline void add_query(int idx, int a, int b)
  {
struct query_node *p = &queries[idx];
p->idx = b;
p->next = tree[a].query;
tree[a].query = p;
}

void dfs(int idx, int depth)
  {
struct edge_node *e;
struct query_node *q;
int i;

tree[idx].visited = 1;
tree[idx].depth = depth;
 for (q = tree[idx].query; q; q = q->next) {
if (!tree[q->idx].visited)
continue;
i = find(q->idx);
q->ans = tree[q->idx].depth + depth - 2*tree[i].depth;
}

 for (e = tree[idx].edge; e; e = e->next) {
if (tree[e->idx].visited)
continue;
dfs(e->idx, depth + e->len);
set[e->idx].parent = idx;
set[e->idx].len = e->len;
}
}

int main()
  {
int n, m, k, i, a, b, len;
char str[16];

freopen("e:\\test\\in.txt", "r", stdin);

scanf("%d%d", &n, &m);
 for (i = 0; i < m*2; i += 2) {
scanf("%d%d%d%s", &a, &b, &len, str);
add_edge(i, a, b, len);
add_edge(i+1, b, a, len);
}
scanf("%d", &k);
 for (i = 0; i < k*2; i += 2) {
scanf("%d%d", &a, &b);
add_query(i, a, b);
add_query(i+1, b, a);
}
dfs(1, 0);
for (i = 0; i < k*2; i += 2)
printf("%d\n", max(queries[i].ans, queries[i+1].ans));

return 0;
}

DFS+RMQ:
#include <stdio.h>

#define MAX_N 40032

int rmq[MAX_N*2][16], seq[MAX_N*2], seq_cnt, map[MAX_N];

 struct edge_node {
struct edge_node *next;
int idx, len;
};
struct edge_node edges[MAX_N*2];

 struct tree_node {
struct edge_node *edge;
int depth, visited;
};
struct tree_node tree[MAX_N];

__inline int min(int a, int b)
  {
return a < b ? a : b;
}

__inline void add_edge(int idx, int a, int b, int len)
  {
struct edge_node *p = &edges[idx];
p->idx = b;
p->len = len;
p->next = tree[a].edge;
tree[a].edge = p;
}

__inline void add_seq(int idx)
  {
seq[seq_cnt] = idx;
if (!map[idx])
map[idx] = seq_cnt;
seq_cnt++;
}

void dfs(int idx, int depth)
  {
struct edge_node *e;

tree[idx].visited = 1;
tree[idx].depth = depth;

 for (e = tree[idx].edge; e; e = e->next) {
if (tree[e->idx].visited)
continue;
add_seq(idx);
add_seq(e->idx);
dfs(e->idx, depth + e->len);
}
}

__inline void rmq_init()
  {
int i, len, j;

for (i = 1; i < seq_cnt; i++)
rmq[i][0] = tree[seq[i]].depth;
 for (i = 1; ; i++) {
len = 1 << i;
if (1 + len > seq_cnt)
break;
for (j = 1; j + len <= seq_cnt; j++)
rmq[j][i] = min(rmq[j][i - 1], rmq[j + len/2][i - 1]);
}
}

__inline int rmq_query(int start, int end)
  {
int len, i;
len = end - start + 1;
for (i = 0; (1 << i) <= len; i++);
i--;
return min(rmq[start][i], rmq[end + 1 - (1 << i)][i]);
}

int main()
  {
int n, m, i, j, a, b, len;
char str[16];

freopen("e:\\test\\in.txt", "r", stdin);

scanf("%d%d", &n, &m);
 for (i = 0; i < m*2; i += 2) {
scanf("%d%d%d%s", &a, &b, &len, str);
add_edge(i, a, b, len);
add_edge(i+1, b, a, len);
}

seq_cnt = 1;
dfs(1, 0);
rmq_init();

scanf("%d", &i);
 while (i--) {
scanf("%d%d", &a, &b);
 if (map[a] > map[b]) {
j = a;
a = b;
b = j;
}
j = rmq_query(map[a], map[b]);
printf("%d\n", tree[a].depth + tree[b].depth - 2*j);
}

return 0;
}

|