Min Max Roads
Time Limit:3000MS Memory Limit:65536KB 64bit IO Format:%lld & %llu
Description
You live in a Big country where there are many bi-directional roads connecting the cities. Since the people of the country are quite intelligent, they designed the country such that there is exactly one path to go from one city to another. A path consists of one or more connected roads.
Here cities are denoted by integers and each road has a cost of traveling. Now you are given the information about the Country. And you are given some queries, each consists of two cities. You have to find the shortest and longest road in the path from one city to another.
Input
Input starts with an integer T(≤5) , denoting the number of test cases.
The first line of each case is a blank line. The next line contains
n(2≤n≤105)
denoting the number of cities. Then there will be
n−1
lines containing three integers each. They will be given in the form
u,v,w(1≤u,v≤n,0<w≤105,u≠v)
meaning that there is a road between
u
and
The next line contains an integer
Output
For each case, print the case number in a single line. Then for each query x y, you should print one line containing the shortest and longest road along the path. See the samples for formatting.
Sample Input
2
6
3 6 50
2 5 30
2 4 300
1 2 100
1 3 200
4
1 4
4 6
2 5
3 5
2
1 2 100
1
1 2
Sample Output
Case 1:
100 300
50 300
30 30
30 200
Case 2:
100 100
Hint
Dataset is huge. Use faster i/o methods.
Problem Setter: Jane Alam Jan
Developed and Maintained by
JANE ALAM JAN
Copyright © 2012
LightOJ, Jane Alam Jan
题意
给你一棵顶点数为
n
的树,然后有
解题思路
可以用LCA倍增法,
O(nlogn)
进行预处理,然后是
O(logn)
查询
u
和
也可以用树链剖分,非常明显,裸题
代码
/*除去冗长的头文件*/
const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int u, v, cost, nxt;
} E[MAXN << 1];
int Head[MAXN], tot;
int deep[MAXN];
int p[MAXN][20];
int Mi[MAXN][20];
int Ma[MAXN][20];
void edge_init() {
tot = 0;
mem(Head, -1);
mem(p, -1);
mem(Ma, 0);
mem(Mi, 0x3f);
}
void add_edge(int u, int v, int cost) {
E[tot].u = u;
E[tot].v = v;
E[tot].cost = cost;
E[tot].nxt = Head[u];
Head[u] = tot ++;
}
void dfs(int u, int pre, int d) {
deep[u] = d;
for(int i = Head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if(v == pre) continue;
dfs(v, u, d + 1);
p[v][0] = u;
Mi[v][0] = E[i].cost;
Ma[v][0] = E[i].cost;
}
}
void b_init(int max_n) {
for(int j = 1; 1 << j <= max_n; j ++) {
for(int i = 1; i <= max_n; i ++) {
if(p[i][j - 1] != -1) {
p[i][j] = p[p[i][j - 1]][j - 1];
Mi[i][j] = min(Mi[i][j - 1], Mi[p[i][j - 1]][j - 1]);
Ma[i][j] = max(Ma[i][j - 1], Ma[p[i][j - 1]][j - 1]);
}
}
}
}
PII LCA(int a, int b) {
int Max = 0, Min = INF;
if(deep[a] < deep[b]) swap(a, b);
int dcp = 0;
for(; 1 << dcp <= deep[a]; dcp ++);
dcp --;
for(int j = dcp; j >= 0; j --) {
if(deep[a] - (1 << j) >= deep[b]) {
Max = max(Max, Ma[a][j]);
Min = min(Min, Mi[a][j]);
a = p[a][j];
}
}
if(a == b) return make_pair(Min, Max);
for(int j = dcp; j >= 0; j --) {
if(p[a][j] != -1 && p[a][j] != p[b][j]) {
Max = max(Max, Ma[a][j]);
Min = min(Min, Mi[a][j]);
Max = max(Max, Ma[b][j]);
Min = min(Min, Mi[b][j]);
a = p[a][j];
b = p[b][j];
}
}
Max = max(Max, Ma[a][0]);
Min = min(Min, Mi[a][0]);
Max = max(Max, Ma[b][0]);
Min = min(Min, Mi[b][0]);
return make_pair(Min, Max);
}
int T, n;
int main() {
#ifndef ONLINE_JUDGE
FIN;
//FOUT;
#endif
IO_Init();
int cas = 1;
scanf("%d", &T);
while(T --) {
int u, v, cost;
edge_init();
scanf("%d", &n);
for(int i = 0; i < n - 1; i ++) {
scanf("%d%d%d", &u, &v, &cost);
add_edge(u, v, cost);
add_edge(v, u, cost);
}
dfs(1, 0, 0);
b_init(n);
int q, a, b;
printf("Case %d:\n", cas ++);
scanf("%d", &q);
while(q --) {
scanf("%d%d", &a, &b);
PII p = LCA(a, b);
printf("%d %d\n", p.first, p.second);
}
}
return 0;
}
树链剖分
/*除去冗长的头文件*/
const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
struct Edge {
int u, v, nxt, cost;
} E[MAXN << 1], TmpE[MAXN << 1];
int Head[MAXN], tot, sz;
int deep[MAXN << 1], fa[MAXN << 1], ve[MAXN << 1], top[MAXN << 1], p[MAXN << 1], fp[MAXN << 1], son[MAXN << 1];
void edge_init() {
tot = 0;
sz = 0;
mem(Head, -1);
}
void add_edge(int u, int v, int cost) {
E[tot].u = u;
E[tot].v = v;
E[tot].cost = cost;
E[tot].nxt = Head[u];
Head[u] = tot ++;
}
void dfs1(int u, int pre, int d) {
deep[u] = d;
fa[u] = pre;
ve[u] = 1;
son[u] = -1;
for(int i = Head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if(v == pre) continue;
dfs1(v, u, d + 1);
ve[u] += ve[v];
if(son[u] == -1 || ve[v] > ve[son[u]]) {
son[u] = v;
}
}
}
void dfs2(int u, int sp) {
top[u] = sp;
p[u] = ++ sz;
fp[p[u]] = u;
if(son[u] == -1) return;
dfs2(son[u], sp);
for(int i = Head[u]; ~i; i = E[i].nxt) {
int v = E[i].v;
if(v == son[u] || v == fa[u]) continue;
dfs2(v, v);
}
}
int sum[2][MAXN << 2];
void push_up(int rt) {
sum[0][rt] = min(sum[0][rt << 1], sum[0][rt << 1 | 1]);
sum[1][rt] = max(sum[1][rt << 1], sum[1][rt << 1 | 1]);
}
void build(int rt, int l, int r) {
sum[1][rt] = 0;
sum[0][rt] = INF;
if(l == r) return;
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
void update(int p, int val, int rt, int l, int r) {
if(l == r) {
sum[0][rt] = sum[1][rt] = val;
return ;
}
int mid = (l + r) >> 1;
if(p <= mid) {
update(p, val, lson);
} else {
update(p, val, rson);
}
push_up(rt);
}
int query(int L, int R, int rt, int l, int r, int flag) {
if(L <= l && r <= R) {
return sum[flag][rt];
}
int mid = (l + r) >> 1;
int ret = flag ? 0 : INF;
if(L <= mid) {
ret = flag ? max(ret, query(L, R, lson, flag)) : min(ret, query(L, R, lson, flag));
}
if(mid < R) {
ret = flag ? max(ret, query(L, R, rson, flag)) : min(ret, query(L, R, rson, flag));
}
return ret;
}
int find(int u, int v, int flag) {
int f1 = top[u], f2 = top[v];
int tmp = flag ? 0 : INF;
while(f1 != f2) {
if(deep[f1] < deep[f2]) {
swap(f1, f2);
swap(u, v);
}
tmp = flag ? max(tmp, query(p[f1], p[u], 1, 1, sz, flag)) : min(tmp, query(p[f1], p[u], 1, 1, sz, flag));
u = fa[f1];
f1 = top[u];
}
if(v == u) return tmp;
if(deep[u] > deep[v]) swap(u, v);
return flag ? max(tmp, query(p[son[u]], p[v], 1, 1, sz, flag)) : min(tmp, query(p[son[u]], p[v], 1, 1, sz, flag));
}
int T, n;
int main() {
#ifndef ONLINE_JUDGE
//FIN;
//FOUT;
#endif
IO_Init();
int cas = 1;
scanf("%d", &T);
while(T --) {
edge_init();
scanf("%d", &n);
for(int i = 0; i < n - 1; i ++) {
scanf("%d%d%d", &TmpE[i].u, &TmpE[i].v, &TmpE[i].cost);
add_edge(TmpE[i].u, TmpE[i].v, TmpE[i].cost);
add_edge(TmpE[i].v, TmpE[i].u, TmpE[i].cost);
}
dfs1(1, 0, 0);
dfs2(1, 1);
build(1, 1, sz);
for(int i = 0; i < n - 1; i ++) {
if(deep[TmpE[i].u] > deep[TmpE[i].v]) swap(TmpE[i].u, TmpE[i].v);
update(p[TmpE[i].v], TmpE[i].cost, 1, 1, sz);
}
printf("Case %d:\n", cas ++);
int q, a, b;
scanf("%d", &q);
while(q --) {
scanf("%d%d", &a, &b);
printf("%d %d\n", find(a, b, 0), find(a, b, 1));
}
}
return 0;
}