UVA 11354 - Bond (最小生成树 + 树链剖分)
做题感悟:这题開始看到时感觉不是树不优点理,一想能够用 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 (最小生成树 + 树链剖分)的更多相关文章
- 【bzoj2238】Mst 最小生成树+树链剖分+线段树
题目描述 给出一个N个点M条边的无向带权图,以及Q个询问,每次询问在图中删掉一条边后图的最小生成树.(各询问间独立,每次询问不对之后的询问产生影响,即被删掉的边在下一条询问中依然存在) 输入 第一行两 ...
- [wikioi 1519]过路费(最小生成树+树链剖分)
题目:http://www.wikioi.com/problem/1519/ 题意:给你一个连通的无向图,每条边都有权值,给你若干个询问(x,y),要输出从x到y的路径上边的最大值的最小值 分析:首先 ...
- Educational Codeforces Round 3 E. Minimum spanning tree for each edge (最小生成树+树链剖分)
题目链接:http://codeforces.com/contest/609/problem/E 给你n个点,m条边. 问枚举每条边,问你加这条边的前提下组成生成树的权值最小的树的权值和是多少. 先求 ...
- 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 ...
- HDU3710 Battle over Cities(最小生成树+树链剖分+倍增+线段树)
Battle over Cities Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Othe ...
- [BZOJ2238]Mst 最小生成树+树链剖分/并查集
链接 题解 先构建出最小生成树,如果删的是非树边,直接输出答案 否则问题转化为,把该边删掉后剩下两个联通块,两个端点分别在两个块内的最小边权,LCT可以维护 不妨换一种思考方向:考虑一条非树边可以代替 ...
- UVA 11354 Bond 最小生成树 + lca
题意 给出一张图,q个询问,每次询问给出uv,找出一条路径,使这条路径上的最大边权是两点所有路径中最小,输出这个值 思路 很显然要先求出最小生成树,任意两点在最小生成树上有唯一路径,并且这条路径上的最 ...
- uva 11354 - Bond(树链拆分)
题目链接:uva 11354 - Bond 题目大意:给定一张图.每次询问两个节点路径上进过边的危急值的最大值的最小值. 解题思路:首先建立最小生成数,然后依据这棵树做树链剖分. #include & ...
- 严格次小生成树[BJWC2010] (树链剖分,倍增,最小生成树)
题目链接 Solution 有几点关键,首先,可以证明次小生成树一定是由最小生成树改变一条边而转化来. 所以需要枚举所有非最小生成树的边\((u,v)\).并且找到 \(u\) 到 \(v\) 的边中 ...
随机推荐
- python学习之-- 动态导入模块
python 动态导入模块方法1: __import__ 说明: 1. 函数功能用于动态的导入模块,主要用于反射或者延迟加载模块. 2. __import__(module)相当于import mod ...
- 【BZOJ4458】GTY的OJ
题面 Description 身为IOI金牌的gtyzs有自己的一个OJ,名曰GOJ.GOJ上的题目可谓是高质量而又经典,他在他的OJ里面定义了一个树形的分类目录,且两个相同级别的目录是不会重叠的.比 ...
- hdu 1599 find the mincost route 最小环
题目链接:HDU - 1599 杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须 ...
- Android的file文件操作详解
Android的file文件操作详解 android的文件操作要有权限: 判断SD卡是否插入 Environment.getExternalStorageState().equals( android ...
- 【mybatis】mybatis中 的# 和 $的区别
mybatis中 的# 和 $的区别 参考地址:https://www.cnblogs.com/sxdcgaq8080/p/10869144.html
- 管理 node 版本,选择 nvm 还是 n?
来源:http://taobaofed.org/blog/2015/11/17/nvm-or-n/ 引子 我本机安装着 nvm,而 node 本来一直运行在 0.x 的老版本上.后来为了跑 ES6,我 ...
- S5PV210之内外存学习
RAM,内部存储器,用来运行程序(DRAM,SRAM,DDR) ROM,外部存储器,存储数据.程序(硬盘,FLASH等) 内存:SRAM,静态内存,容量下,价格高,不需要初始化,上电后直接使用 DRA ...
- JAVA之HashMap集合
/** * HashMap集合讲解 * HashMap集合不允许集合元素的Key重复 */package com.test; import java.util.*; public class test ...
- 16个Linux服务器监控命令
在不同的Linux发行版中,会有不同的GUI程序可以显示各种系统信息,比如SUSE linux发行版中,就有非常棒的图形化的配置和管理工具YaST,KDE桌面环境里的KDE System Guard也 ...
- testng执行报错:org.testng.TestNGException: Cannot find class in classpath
org.testng.TestNGException: Cannot find class in classpath 解决办法:project->clean 再次执行正常运行