题目链接~~>

做题感悟:这题開始看到时感觉不是树不优点理,一想能够用 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. 计蒜客 28315.Excellent Engineers-线段树(单点更新、区间最值) (Benelux Algorithm Programming Contest 2014 Final ACM-ICPC Asia Training League 暑假第一阶段第二场 E)

    先写这几道题,比赛的时候有事就只签了个到. 题目传送门 E. Excellent Engineers 传送门 这个题的意思就是如果一个人的r1,r2,r3中的某一个比已存在的人中的小,就把这个人添加到 ...

  2. 51 nod 1419 最小公倍数挑战【数论/互质+思维】

    1419 最小公倍数挑战 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 几天以前,我学习了最小公倍数.玩得挺久了 ...

  3. servlet方法

    1.每一个Servlet都必须要实现Servlet接口,GenericServlet是个通用的.不特定于任何协议的Servlet,它实现了Servlet接口,而HttpServlet继承于Generi ...

  4. Python的网络编程[4] -> DHCP 协议[1] -> DHCP 的 Python 实现

    DHCP实现 / DHCP Implement 目录 DHCP 服务器建立过程 DHCP 报文加码实现过程 下面介绍建立一个简单的DHCP服务器,主要用于对基本的DHCP请求进行响应,目前只提供一个I ...

  5. UOJ 180【UR #12】实验室外的攻防战

    http://uoj.ac/contest/25/problem/180 从前往后对比串A,B 当$A_i,B_i$不相同时找到$B_i$在A中的位置j 若$min{A_1,A_2,A_3...... ...

  6. POJ2955 Brackets(区间DP)

    给一个括号序列,求有几个括号是匹配的. dp[i][j]表示序列[i,j]的匹配数 dp[i][j]=dp[i+1][j-1]+2(括号i和括号j匹配) dp[i][j]=max(dp[i][k]+d ...

  7. 用swift开发自己的MacOS锁屏软件(3)

    前两篇中实现了MacOS端的锁屏软件,现在需要再实现一个移动端的app用来实现和mac的通信,以后的文章可能就会两个项目来回穿插了. 写完MacOS的软件又回来接着写iOS真的是享受,看着堆积如山的各 ...

  8. eclipse无法导入Android工程的解决办法

    我以前在windows平台下写的android源代码无法通过import"existing project into workspace"导入到mac的eclipse中,直接搜不见 ...

  9. Android Developer -- Bluetooth篇 概述

    Bluetooth 安卓平台支持蓝牙网络协议栈,它允许设备与其他蓝牙设备进行无线交换数据.应用程序框架通过安卓蓝牙APIs提供访问蓝牙功能.这些APIs使应用程序通过无线连接到其他蓝牙设备,使点对点和 ...

  10. Spring/Spring MVC/Spring Boot实现跨域

    说明:Spring MVC和Spring Boot其实用的都是同一套. CORS介绍请看这里:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Acc ...