题目链接:uva 11354 - Bond

题目大意:给定一张图。每次询问两个节点路径上进过边的危急值的最大值的最小值。

解题思路:首先建立最小生成数,然后依据这棵树做树链剖分。

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm> using namespace std;
const int maxn = 50005;
const int INF = 0x3f3f3f3f; struct Edge {
int u, v, w;
Edge (int u = 0, int v = 0, int w = 0) { set(u, v, w); }
void set(int u, int v, int w) {
this->u = u;
this->v = v;
this->w = w;
}
friend bool operator < (const Edge& a, const Edge& b) {
return a.w < b.w;
}
}ed[maxn * 2]; int N, M, Q, ne, f[maxn], first[maxn], jump[maxn * 2], val[maxn];
int id, idx[maxn], top[maxn], far[maxn], son[maxn], dep[maxn], cnt[maxn];
vector<Edge> vec; inline int getfar(int x) {
return x == f[x] ? x : f[x] = getfar(f[x]);
} inline void add_Edge (int u, int v, int w) {
ed[ne].set(u, v, w);
jump[ne] = first[u];
first[u] = ne++;
} void dfs (int u, int pre, int d) {
far[u] = pre;
dep[u] = d;
son[u] = 0;
cnt[u] = 1; for (int i = first[u]; i + 1; i = jump[i]) {
int v = ed[i].v;
if (v == pre)
continue;
dfs(v, u, d + 1);
cnt[u] += cnt[v];
if (cnt[son[u]] < cnt[v])
son[u] = v;
}
} void dfs (int u, int rot) {
top[u] = rot;
idx[u] = ++id;
if (son[u])
dfs(son[u], rot);
for (int i = first[u]; i + 1; i = jump[i]) {
int v = ed[i].v;
if (v == far[u] || v == son[u])
continue;
dfs(v, v);
}
} #define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
int lc[maxn << 2], rc[maxn << 2], s[maxn << 2]; inline void pushup(int u) {
s[u] = max(s[lson(u)], s[rson(u)]);
} void build (int u, int l, int r) {
lc[u] = l;
rc[u] = r; if (l == r) {
s[u] = val[l];
return;
} int mid = (l + r) / 2;
build(lson(u), l, mid);
build(rson(u), mid + 1, r);
pushup(u);
} int query(int u, int l, int r) {
if (l <= lc[u] && rc[u] <= r)
return s[u];
int mid = (lc[u] + rc[u]) / 2, ret = 0;
if (l <= mid)
ret = max(ret, query(lson(u), l, r));
if (r > mid)
ret = max(ret, query(rson(u), l, r));
return ret;
} void init () {
int u, v, w;
ne = id = 0;
vec.clear();
memset(first, -1, sizeof(first));
for (int i = 1; i <= N; i++)
f[i] = i; for (int i = 0; i < M; i++) {
scanf("%d%d%d", &u, &v, &w);
vec.push_back(Edge(u, v, w));
}
sort(vec.begin(), vec.end());
for (int i = 0; i < vec.size(); i++) {
int p = getfar(vec[i].u);
int q = getfar(vec[i].v);
if (p == q)
continue;
add_Edge(vec[i].u, vec[i].v, vec[i].w);
add_Edge(vec[i].v, vec[i].u, vec[i].w);
f[p] = q;
} dfs(1, 0, 0);
dfs(1, 1);
for (int i = 0; i < N - 1; i++) {
int t = i * 2;
u = (dep[ed[t].u] < dep[ed[t].v] ? ed[t].v : ed[t].u);
val[idx[u]] = ed[t].w;
}
build(1, 1, N);
} int solve (int u, int v) {
int p = top[u], q = top[v], ret = 0;
while (p != q) {
if (dep[p] < dep[q]) {
swap(p, q);
swap(u, v);
}
ret = max(ret, query(1, idx[p], idx[u]));
u = far[p];
p = top[u];
}
if (u == v)
return ret;
if (dep[u] > dep[v])
swap(u, v);
ret = max(ret, query(1, idx[son[u]], idx[v]));
return ret;
} int main () {
int cas = 0;
while (scanf("%d%d", &N, &M) == 2) {
if (cas++)
printf("\n"); init(); int u, v;
scanf("%d", &Q);
while (Q--) {
scanf("%d%d", &u, &v);
printf("%d\n", solve(u, v));
}
}
return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

uva 11354 - Bond(树链拆分)的更多相关文章

  1. hdu5044 Tree 树链拆分,点细分,刚,非递归版本

    hdu5044 Tree 树链拆分.点细分.刚,非递归版本 //#pragma warning (disable: 4786) //#pragma comment (linker, "/ST ...

  2. UVA 11354 - Bond (最小生成树 + 树链剖分)

    题目链接~~> 做题感悟:这题開始看到时感觉不是树不优点理,一想能够用 Kruskal 处理成树 ,然后就好攻克了. 解题思路: 先用 Kruskal 处理出最小生成树.然后用树链剖分 + 线段 ...

  3. Codeforces 191C Fools and Roads(树链拆分)

    题目链接:Codeforces 191C Fools and Roads 题目大意:给定一个N节点的数.然后有M次操作,每次从u移动到v.问说每条边被移动过的次数. 解题思路:树链剖分维护边,用一个数 ...

  4. Codeforces 191 C Fools and Roads (树链拆分)

    主题链接~~> 做题情绪:做了HDU 5044后就感觉非常easy了. 解题思路: 先树链剖分一下,把树剖分成链,由于最后全是询问,so~能够线性操作.经过树链剖分后,就会形成很多链,可是每条边 ...

  5. HYSBZ 2243 染色 (树链拆分)

    主题链接~~> 做题情绪:这题思路好想.调试代码调试了好久.第一次写线段树区间合并. 解题思路: 树链剖分 + 线段树区间合并 线段树的端点记录左右区间的颜色.颜色数目.合并的时候就用区间合并的 ...

  6. poj 3237 Tree(树链拆分)

    题目链接:poj 3237 Tree 题目大意:给定一棵树,三种操作: CHANGE i v:将i节点权值变为v NEGATE a b:将ab路径上全部节点的权值变为相反数 QUERY a b:查询a ...

  7. hdu 4912 Paths on the tree(树链拆分+贪婪)

    题目链接:hdu 4912 Paths on the tree 题目大意:给定一棵树,和若干个通道.要求尽量选出多的通道,而且两两通道不想交. 解题思路:用树链剖分求LCA,然后依据通道两端节点的LC ...

  8. BZOJ 3589 动态树 树链拆分+纳入和排除定理

    标题效果:鉴于一棵树.每个节点有一个右值,所有节点正确启动值他们是0.有两种操作模式,0 x y代表x右所有点的子树的根值添加y. 1 k a1 b1 a2 b2 --ak bk代表质疑. 共同拥有者 ...

  9. POJ 3237 Tree (树链拆分)

    主题链接~~> 做题情绪:了. 解题思路: 主要注意如何区间更新就ok了 . 树链剖分就是树上的线段树. 代码: #include<iostream> #include<sst ...

随机推荐

  1. Eclipse在Jar形成和应用程序包

    最近的熟悉Java语言.在学习过程中Eclipse经常使用再熟悉它.本文简单说下Jar形成和应用程序包. Java在Jar相当于包C/C++该lib库,它是.class文件打包:经常使用Jar包有AP ...

  2. HDU 1698 Just a Hook (段树更新间隔)

    Problem Description In the game of DotA, Pudge's meat hook is actually the most horrible thing for m ...

  3. V微软S2015下载:开展Win10/Linux/iOS多平台软件

    微软VS2015下载:开展Win10/Linux/iOS多平台软件 资源:IT之家作者:子非         责任编辑:子非   11月13日消息,微软刚刚宣布了 Visual Studio 2015 ...

  4. QlikView同button控制转换图表类型(例如,变成一个垂直的条形图)

    QlikView图表可以通过检查一些可以为图表类型的转换非常方便进行配置,允许用户选择上面的图就是看条形图或柱状图或垂直方向图detail数据. 在Fast Type Change中选中如上图所看到的 ...

  5. Apple Watch 1.0 开发介绍 2.1 WatchKit Apps UI要点

    实现app的开始是定义storyboard场景.每个场景定义了app的一部分界面.可以为不同的尺寸自定义场景. 组装storyboard界面 WatchKit app和iOS app的布局模式不同.组 ...

  6. 开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

    原文:[原创]开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器                本博客所有文章分类的总目录:http://www.cnblogs.com/asxiny ...

  7. C# - is

     Checks if an object is compatible with a given type. An is expression evaluates to true if the pr ...

  8. HDU 1054 Strategic Game(树形DP)

    Problem Description Bob enjoys playing computer games, especially strategic games, but sometimes he ...

  9. Bash多个配置文件通常用于

    Login shells阅读下面的启动文件: 文件 内容 /etc/profile 对全部用户开放的全局配置文件 ~/.bash_profile 某个用户个人的启动文件,能用作个人的全局设置 ~/.b ...

  10. GIF/PNG/JPG和WEBP/base64/apng图片优点和缺点整理(转)

    如何获取图片对应的base64字符串呢? 1:使用代码获取: 运行下面代码 var reader = new FileReader(), htmlImage; reader.onload = func ...