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\) 的边中 ...
随机推荐
- 解决iOS10的Safari下Meta设置user-scalable=no无效的方法
苹果为了提高Safari中网站的辅助功能,屏蔽了Meta下的user-scalable=no功能.所以在iOS10下面,就算加上user-scalable=no,Safari浏览器也能支持手动缩放. ...
- Codeforces Beta Round #4 (Div. 2 Only) C. Registration system【裸hash/map】
C. Registration system time limit per test 5 seconds memory limit per test 64 megabytes input standa ...
- POJ 1298 The Hardest Problem Ever【字符串】
Julius Caesar lived in a time of danger and intrigue. The hardest situation Caesar ever faced was ke ...
- UVA 1151 Buy or Build MST(最小生成树)
题意: 在平面上有n个点,要让所有n个点都连通,所以你要构造一些边来连通他们,连通的费用等于两个端点的欧几里得距离的平方.另外还有q个套餐,可以购买,如果你购买了第i个套餐,该套餐中的所有结点将变得相 ...
- Ribbon负载均衡(四)
一.Ribbon定义 spring cloud Ribbon是基于Netflix Ribbon实现的一套客户端,负载均衡工具 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端 ...
- Jmeter插件之PerfMon监控插件使用说明
PerfMon是Jmeter用来监控系统资源的一款插件,可以用来监控系统的cpu.内存.I/O等性能指标. 首先是Jmeter的插件安装,需要先下载JMeter Plugins Manager这个插件 ...
- [BZOJ2460][BJOI2011]元素(线性基)
2460: [BeiJing2011]元素 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2195 Solved: 1119[Submit][Sta ...
- [POI2014]Tourism
题目大意: 给定一个$n(n\le20000)$条个点,$m(m\le25000)$条边的无向图,保证图中最长路径上的点数不超过$10$.对一个点染色的代价是$w_i$.求使得每个结点都被染色或至少有 ...
- Log4j记录日志到数据库
1.自定义输出消息 /** * 参数化消息 * @author Johnson.Lee * */ public interface ParameterizedMessage extends Seria ...
- NHibernate官方文档——第八章 继承映射(Inheritance Mapping)
本文翻译自NHibernate官方文档NHibernate Reference Documentation 4.1. 受限于个人知识水平,有些地方翻译可能不准确,但是我还是希望我的这些微薄的努力能为他 ...