题目链接~~>

做题感悟:这题開始看到时感觉不是树不优点理,一想能够用 Kruskal 处理成树 ,然后就好攻克了。

解题思路:

先用 Kruskal 处理出最小生成树。然后用树链剖分 + 线段树处理就能够了。

代码:

#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std ;
#define INT long long int
#define L(x) (x * 2)
#define R(x) (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1000000007 ;
const int MY = (1<<5) + 5 ;
const int MX = 100000 + 5 ;
int n ,m ,nx ,idx ,num ;
int head[MX] ,ti[MX] ,siz[MX] ,son[MX] ,father[MX] ,top[MX] ,dep[MX] ;
struct NODE
{
int u ,v ,w ;
}e[MX] ;
struct MNODE
{
int u ,v ,w ;
}t[MX] ;
struct Edge
{
int u ,v ,w ,next ;
}E[MX*2] ;
void addedge(int u ,int v ,int w)
{
E[num].v = v ; E[num].w = w ; E[num].next = head[u] ; head[u] = num++ ;
E[num].v = u ; E[num].w = w ; E[num].next = head[v] ; head[v] = num++ ;
}
bool cmp(NODE a ,NODE b)
{
return a.w < b.w ;
}
int find(int u)
{
if(father[u] != u)
return find(father[u]) ;
else return u ;
}
void Kruskal()
{
nx = 1 ;
int u ,v ,fa ,fb ;
sort(e ,e+m ,cmp) ;
for(int i = 0 ;i <= n ; ++i)
father[i] = i ;
for(int i = 0 ;i < m ; ++i)
{
u = e[i].u ; v = e[i].v ;
fa = find(u) ;
fb = find(v) ;
if(fa != fb)
{
father[fa] = fb ;
addedge(u ,v ,e[i].w) ;
t[nx].u = u ; t[nx].v = v ; t[nx++].w = e[i].w ;
}
}
}
void dfs_find(int u ,int fa)
{
dep[u] = dep[fa] + 1 ;
father[u] = fa ;
siz[u] = 1 ;
son[u] = 0 ;
for(int i = head[u] ;i != -1 ;i = E[i].next)
{
int v = E[i].v ;
if(v == fa) continue ;
dfs_find(v ,u) ;
siz[u] += siz[v] ;
if(siz[son[u]] < siz[v]) son[u] = v ;
}
}
void dfs_time(int u ,int fa)
{
top[u] = fa ;
ti[u] = idx++ ;
if(son[u]) dfs_time(son[u] ,top[u]) ;
for(int i = head[u] ;i != -1 ;i = E[i].next)
{
int v = E[i].v ;
if(v == father[u] || v == son[u]) continue ;
dfs_time(v ,v) ;
}
}
struct node
{
int le ,rt ,c ;
}T[MX*4] ;
void build(int i ,int le ,int rt)
{
T[i].le = le ; T[i].rt = rt ;
T[i].c = 0 ;
if(le == rt) return ;
int Mid = (le + rt)>>1 ;
build(L(i) ,le ,Mid) ;
build(R(i) ,Mid+1 ,rt) ;
}
void update(int i ,int pos ,int w)
{
if(T[i].le == T[i].rt)
{
T[i].c = w ;
return ;
}
int Mid = (T[i].le + T[i].rt)>>1 ;
if(pos <= Mid) update(L(i) ,pos ,w) ;
else update(R(i) ,pos ,w) ;
T[i].c = max(T[L(i)].c ,T[R(i)].c) ;
}
int section(int i ,int le ,int rt)
{
if(T[i].le == le && T[i].rt == rt)
return T[i].c ;
int Mid = (T[i].le + T[i].rt)>>1 ;
if(le > Mid) return section(R(i) ,le ,rt) ;
else if(rt <= Mid) return section(L(i) ,le ,rt) ;
else
return max(section(L(i) ,le ,Mid) ,section(R(i) ,Mid+1 ,rt)) ;
}
int LCA(int u ,int v)
{
int ans = 0 ;
while(top[u] != top[v])
{
if(dep[top[u]] < dep[top[v]])
swap(u ,v) ;
ans = max(ans ,section(1 ,ti[top[u]] ,ti[u])) ;
u = father[top[u]] ;
}
if(dep[u] > dep[v]) swap(u ,v) ;
if(u != v)
ans = max(ans ,section(1 ,ti[u]+1 ,ti[v])) ;
return ans ;
}
int main()
{
int u ,v ,Q ;
bool first = false ;
while(~scanf("%d%d" ,&n ,&m))
{
if(first) puts("") ;
first = true ;
num = 0 ;
memset(head ,-1 ,sizeof(head)) ;
for(int i = 0 ;i < m ; ++i)
scanf("%d%d%d" ,&e[i].u ,&e[i].v ,&e[i].w) ;
Kruskal() ;
dep[1] = siz[0] = 0 ;
dfs_find(1 ,1) ;
idx = 1 ;
dfs_time(1 ,1) ;
build(1 ,1 ,n) ;
for(int i = 1 ;i < nx ; ++i)
{
if(dep[t[i].u] < dep[t[i].v])
swap(t[i].u ,t[i].v) ;
update(1 ,ti[t[i].u] ,t[i].w) ;
}
scanf("%d" ,&Q) ;
for(int i = 0 ;i < Q ; ++i)
{
scanf("%d%d" ,&u ,&v) ;
printf("%d\n" ,LCA(u ,v)) ;
}
}
return 0 ;
}

倍增法 (类似RMQ)

代码:

#include<iostream>
#include<sstream>
#include<map>
#include<cmath>
#include<fstream>
#include<queue>
#include<vector>
#include<sstream>
#include<cstring>
#include<cstdio>
#include<stack>
#include<bitset>
#include<ctime>
#include<string>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std ;
#define INT long long int
#define L(x) (x * 2)
#define R(x) (x * 2 + 1)
const int INF = 0x3f3f3f3f ;
const double esp = 0.0000000001 ;
const double PI = acos(-1.0) ;
const int mod = 1000000007 ;
const int MY = (1<<5) + 5 ;
const int MX = 100000 + 5 ;
const int S = 20 ;
int n ,m ,idx ,num ,nx ;
int value[MX][25] ,p[MX][25] ,ti[MX] ,father[MX] ,dep[MX] ,head[MX] ;
struct TEMP
{
int u ,v ,w ;
}A[MX] ;
struct Edge
{
int v ,w ,next ;
}E[MX*2] ;
bool cmp(TEMP a ,TEMP b)
{
return a.w < b.w ;
}
int find(int u)
{
if(father[u] != u)
return find(father[u]) ;
return u ;
}
void addedge(int u ,int v ,int w)
{
E[num].v = v ; E[num].w = w ; E[num].next = head[u] ; head[u] = num++ ;
E[num].v = u ; E[num].w = w ; E[num].next = head[v] ; head[v] = num++ ;
}
void Kruskal()
{
nx = 1 ;
int fa ,fb ;
sort(A ,A+m ,cmp) ;
for(int i = 0 ;i <= n ; ++i)
father[i] = i ;
for(int i = 0 ;i < m ; ++i)
{
fa = find(A[i].u) ;
fb = find(A[i].v) ;
if(fa != fb)
{
father[fa] = fb ;
addedge(A[i].u ,A[i].v ,A[i].w) ;
}
}
}
void dfs_find(int u ,int fa ,int w)
{
dep[u] = dep[fa] + 1 ;
p[u][0] = fa ;
value[u][0] = w ;
for(int i = 1 ;i <= S ; ++i)
{
p[u][i] = p[p[u][i-1]][i-1] ;
value[u][i] = max(value[u][i-1] ,value[p[u][i-1]][i-1]) ;
}
for(int i = head[u] ;i != -1 ;i = E[i].next)
{
int v = E[i].v ;
if(v == fa) continue ;
dfs_find(v ,u ,E[i].w) ;
}
}
int LCA(int u ,int v)
{
int ans = 0 ;
if(dep[u] > dep[v]) swap(u ,v) ;
if(dep[u] < dep[v])
{
int d = dep[v] - dep[u] ;
for(int i = 0 ;i <= S ; ++i)
if(d&(1<<i))
{
ans = max(ans ,value[v][i]) ;
v = p[v][i] ;
}
}
if(u != v)
{
for(int i = S ;i >= 0 ; --i)
if(p[u][i] != p[v][i])
{
ans = max(ans ,value[u][i]) ;
ans = max(ans ,value[v][i]) ;
u = p[u][i] ;
v = p[v][i] ;
}
ans = max(ans ,value[u][0]) ;
ans = max(ans ,value[v][0]) ;
}
return ans ;
}
void init()
{
num = 0 ;
memset(head ,-1 ,sizeof(head)) ;
memset(ti ,0 ,sizeof(ti)) ;
memset(value ,0 ,sizeof(value)) ;
memset(p ,0 ,sizeof(p)) ;
memset(dep ,0 ,sizeof(dep)) ;
}
int main()
{
//freopen("input.txt" ,"r" ,stdin) ;
int u ,v ,Q ;
bool first = false ;
while(~scanf("%d%d" ,&n ,&m))
{
if(first) puts("") ;
first = true ;
init() ;
for(int i = 0 ;i < m ; ++i)
scanf("%d%d%d" ,&A[i].u ,&A[i].v ,&A[i].w) ;
Kruskal() ;
dep[1] = 0 ;
dfs_find(1 ,1 ,0) ;
scanf("%d" ,&Q) ;
while(Q--)
{
scanf("%d%d" ,&u ,&v) ;
printf("%d\n" ,LCA(u ,v)) ;
}
}
return 0 ;
}

UVA 11354 - Bond (最小生成树 + 树链剖分)的更多相关文章

  1. 【bzoj2238】Mst 最小生成树+树链剖分+线段树

    题目描述 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的边在下一条询问中依然存在) 输入 第一行两 ...

  2. [wikioi 1519]过路费(最小生成树+树链剖分)

    题目:http://www.wikioi.com/problem/1519/ 题意:给你一个连通的无向图,每条边都有权值,给你若干个询问(x,y),要输出从x到y的路径上边的最大值的最小值 分析:首先 ...

  3. Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)

    题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...

  4. Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树+树链剖分+线段树

    E. Minimum spanning tree for each edge time limit per test 2 seconds memory limit per test 256 megab ...

  5. HDU3710 Battle over Cities(最小生成树+树链剖分+倍增+线段树)

    Battle over Cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Othe ...

  6. [BZOJ2238]Mst 最小生成树+树链剖分/并查集

    链接 题解 先构建出最小生成树,如果删的是非树边,直接输出答案 否则问题转化为,把该边删掉后剩下两个联通块,两个端点分别在两个块内的最小边权,LCT可以维护 不妨换一种思考方向:考虑一条非树边可以代替 ...

  7. UVA 11354 Bond 最小生成树 + lca

    题意 给出一张图,q个询问,每次询问给出uv,找出一条路径,使这条路径上的最大边权是两点所有路径中最小,输出这个值 思路 很显然要先求出最小生成树,任意两点在最小生成树上有唯一路径,并且这条路径上的最 ...

  8. uva 11354 - Bond(树链拆分)

    题目链接:uva 11354 - Bond 题目大意:给定一张图.每次询问两个节点路径上进过边的危急值的最大值的最小值. 解题思路:首先建立最小生成数,然后依据这棵树做树链剖分. #include & ...

  9. 严格次小生成树[BJWC2010] (树链剖分,倍增,最小生成树)

    题目链接 Solution 有几点关键,首先,可以证明次小生成树一定是由最小生成树改变一条边而转化来. 所以需要枚举所有非最小生成树的边\((u,v)\).并且找到 \(u\) 到 \(v\) 的边中 ...

随机推荐

  1. asp.net 网站模板怎么用,就是16aspx上面下下来的模板,里面有个sln文件,其他全是文件夹的东西

    .net写的程序模板一般都被写死了.那样只有通过程序改了.

  2. H. Fake News (medium)

    H. Fake News (medium) 题意 以前是给出 S T 串,问在 S 中有多少个子串为 T 的个数,子串可以不连续,保持位置相对一致. 现在给出 n ,要你构造 S T 串. 分析 这种 ...

  3. POJ 2763 Housewife Wind(树链剖分)(线段树单点修改)

    Housewife Wind Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 10378   Accepted: 2886 D ...

  4. UVA 11396 Claw Decomposition 染色

    原题链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...

  5. kong后台接口

    在nginx-kong.lua中,require('lapis').serve('kong.api'),先require文件/usr/local/share/lua/5.1/lapis/init.lu ...

  6. DML数据操纵语言

    --创建表T_HQ_BM2 --create table t_hq_bm2 as select * from t_hq_bm; commit; --添加行内容 --insert into t_hq_b ...

  7. extjs combo中给Store插入一条数据

    { xtype: 'combo', columnWidth: .55, name: 'AQLLevel', store: Ext.create('Scripts.Code.Common.store.I ...

  8. Linux查看哪些进程用了Swap分区

    如果系统的物理内存用光了,则会用到swap.系统就会跑得很慢,但仍能运行;如果Swap空间用光了,那么系统就会发生错误.通常会出现“application is out of memory”的错误,严 ...

  9. 新建一个兼容eclipse和myeclipse、IDEA都兼容的项目结构(maven)

    以下观点为个人理解,没实践过,后续再实现. 思路: 1.eclipse和myeclipse.IDEA这些开发工具新建的各自的项目时,都有自己的一套思路,项目结构都有各自的特点. 2.如果是这些开发工具 ...

  10. Visio文件转EPS文件

    Visio转eps by gaihf@水木 看了前人写的关于Visio转EPS的文章,但是实践过程中还是碰到几个棘手的问题.现在这些问题终于解决了,把自己的一点体会分享给大家. 很多人习惯用Visio ...