【题目链接】

http://www.lydsy.com/JudgeOnline/problem.php?id=3732

【题意】

给定一个无向图,处理若干询问:uv路径上最长的边最小是多少?

【思路一】

最小生成树+倍增算法。

同NOIP2013货车运输。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 1e5+;
const int M = 2e5+;
const int D = ;
const int inf = 2e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,w,nxt;
bool operator < (const Edge& rhs) const{
return w<rhs.w;
}
}e[M];
int en=,front[N];
void adde(int u,int v,int w)
{
e[++en]=(Edge){u,v,w,front[u]}; front[u]=en;
}
vector<Edge> es; int n,m,K,p[N],_max[N][D],fa[N][D],dep[N]; int ifind(int u)
{
return u==p[u]? u:p[u]=ifind(p[u]);
} void Kruskal()
{
sort(es.begin(),es.end());
FOR(i,,(int)es.size()-) {
int u=es[i].u,v=es[i].v,w=es[i].w;
int x=ifind(u),y=ifind(v);
if(x!=y) {
p[x]=y;
adde(u,v,w); adde(v,u,w);
}
}
}
void dfs(int u,int father)
{
trav(u,i) {
int v=e[i].v;
if(v!=father) {
fa[v][]=u;
_max[v][]=e[i].w;
dep[v]=dep[u]+;
FOR(j,,D-) {
fa[v][j]=fa[fa[v][j-]][j-];
_max[v][j]=max(_max[v][j-],_max[fa[v][j-]][j-]);
}
dfs(v,u);
}
}
} int query(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v],ans=-inf;
FOR(i,,D-)
if(t&(<<i)) {
ans=max(ans,_max[u][i]);
u=fa[u][i];
}
if(u==v) return ans;
for(int i=D-;i>=;i--)
if(fa[u][i]!=fa[v][i]) {
ans=max(ans,max(_max[u][i],_max[v][i]));
u=fa[u][i],v=fa[v][i];
}
ans=max(ans,max(_max[u][],_max[v][]));
return ans;
} int main()
{
n=read(),m=read(),K=read();
FOR(i,,n) FOR(j,,D-) _max[i][j]=-inf;
FOR(i,,n) p[i]=i;
FOR(i,,m) {
int u=read(),v=read(),w=read();
es.push_back((Edge){u,v,w,});
}
Kruskal();
dfs(,-);
FOR(i,,K) {
int u=read(),v=read();
printf("%d\n",query(u,v));
}
return ;
}

【思路二】

用LCT换个姿势AC。LCT维护最小生成树?

给每条边每个点开一个LCT结点,边的maxe初始为自己,点的maxe为0。对于新加的一条边,找到u->v目前的最大边与之比较,如果更小则切断原来的边连上新的边。u,v之间连边的时候以边界点为中间点。

【代码】

 #include<cstdio>
#include<cstring>
#include<iostream>
#define FOR(a,b,c) for(int a=b;a<=c;a++)
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
using namespace std; typedef long long ll;
typedef unsigned int ul;
const int N = 4e5+; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge { int u,v,w;
}e[N<<]; namespace LCT { struct Node {
Node *ch[],*fa;
int rev,id,maxe;
Node() ;
void reverse() {
rev^=;
swap(ch[],ch[]);
}
void up_push() {
if(fa->ch[]==this||fa->ch[]==this)
fa->up_push();
if(rev) {
ch[]->reverse();
ch[]->reverse();
rev=;
}
}
void maintain() {
int _max=-;
if(e[ch[]->maxe].w>_max)
_max=e[ch[]->maxe].w,maxe=ch[]->maxe;
if(e[ch[]->maxe].w>_max)
_max=e[ch[]->maxe].w,maxe=ch[]->maxe;
if(e[id].w>_max) maxe=id;
}
} *null=new Node,T[N],E[N<<];
Node::Node() {
id=maxe=rev=;
fa=ch[]=ch[]=null;
} void rot(Node* o,int d) {
Node *p=o->fa;
p->ch[d]=o->ch[d^];
o->ch[d^]->fa=p;
o->ch[d^]=p;
o->fa=p->fa;
if(p==p->fa->ch[])
p->fa->ch[]=o;
else if(p==p->fa->ch[])
p->fa->ch[]=o;
p->fa=o;
p->maintain();
}
void splay(Node *o) {
o->up_push();
Node *nf,*nff;
while(o->fa->ch[]==o||o->fa->ch[]==o) {
nf=o->fa,nff=nf->fa;
if(o==nf->ch[]) {
if(nf==nff->ch[]) rot(nf,);
rot(o,);
} else {
if(nf==nf->ch[]) rot(nf,);
rot(o,);
}
}
o->maintain();
}
void Access(Node* o) {
Node *son=null;
while(o!=null) {
splay(o);
o->ch[]=son;
o->maintain();
son=o; o=o->fa;
}
}
void evert(Node* o) {
Access(o);
splay(o);
o->reverse();
}
void Link(Node* u,Node* v) {
evert(u);
u->fa=v;
}
void Cut(Node* u,Node* v) {
evert(u);
Access(v); splay(v);
u->fa=v->ch[]=null;
v->maintain();
}
Node* find(Node* o) {
while(o->fa!=null) o=o->fa;
return o;
} }
using namespace LCT; const int inf = 1e9+; int n,m,K; int query(Node *u,Node *v)
{
evert(u);
Access(v),splay(v);
return v->maxe;
}
void insert(Node *u,Node *v,int x)
{
if(e[x].u==e[x].v) return ;
if(find(u)==find(v)) {
int maxe=query(u,v);
if(e[x].w>=e[maxe].w) return ;
Cut(&E[maxe],&T[e[maxe].v]);
Cut(&E[maxe],&T[e[maxe].u]);
}
Link(u,&E[x]);
Link(v,&E[x]);
} int main()
{
n=read(),m=read(),K=read();
FOR(i,,m) E[i].id=E[i].maxe=i;
FOR(i,,m) {
e[i].u=read(),e[i].v=read(),e[i].w=read();
insert(&T[e[i].u],&T[e[i].v],i);
}
FOR(i,,K) {
int u=read(),v=read();
printf("%d\n",e[query(&T[u],&T[v])].w);
}
return ;
}

bzoj 3732 Network(最短路+倍增 | LCT)的更多相关文章

  1. BZOJ 3732: Network 最小生成树 倍增

    3732: Network 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 &l ...

  2. BZOJ 3732 Network —— 最小生成树 + 倍增LCA

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3732 Description 给你N个点的无向图 (1 <= N <= 15, ...

  3. BZOJ 3732 Network Kruskal+倍增LCA

    题目大意:给定一个n个点m条边的无向连通图.k次询问两点之间全部路径中最长边的最小值 NOIP2013 货车运输.差点儿就是原题...仅仅只是最小边最大改成了最大边最小.. . 首先看到最大值最小第一 ...

  4. BZOJ 3732 Network

    2016.1.28 纪念我BZOJ第一题 Description 给你N个点的无向图 (1 <= N <= 15,000),记为:1…N. 图中有M条边 (1 <= M <= ...

  5. bzoj 3732: Network 树上两点边权最值

    http://www.lydsy.com/JudgeOnline/problem.php?id=3732 首先想到,要使得最长边最短,应该尽量走最短的边,在MST上. 然后像LCA那样倍增娶个最大值 ...

  6. BZOJ 3732 Network Link-Cut-Tree (我是认真的!!

    题目大意:给定一个n个点m条边的无向连通图.k次询问两点之间全部路径中最长边的最小值 LCT的裸题! 首先维护一个动态的最小生成树,然后每次增加边时删除两点间路径上权值最大的边.最后询问时直接求x到y ...

  7. bzoj 3732: Network【克鲁斯卡尔+树链剖分】

    先做最小生成树,这样就保证了最大值最小 然后随便用个什么东西维护一下最大值,我用的树剖log^2,倍增会更快 #include<iostream> #include<cstdio&g ...

  8. BZOJ 3732 Network 【模板】kruskal重构树

    [题解] 首先,我们可以发现,A到B的所有路径中,最长边的最小值一定在最小生成树上.我们用Kruskal最小生成树时,假设有两个点集U,V,若加入一条边w(u,v)使U,V联通,那么w就是U中每个点到 ...

  9. Kruskal重构树+LCA || BZOJ 3732: Network

    题面:https://www.lydsy.com/JudgeOnline/problem.php?id=3732 题解:Kruskal重构树板子 代码: #include<cstdio> ...

随机推荐

  1. Ios 弹框 MJPopup,KxMenu

    IOS 弹框 如果直接弹出一个自定义的视图 可以选用第三方: MJPopup 弹出: if(!bandview) { bandview=[[[NSBundle mainBundle]loadNibNa ...

  2. QT源码解析(一) QT创建窗口程序、消息循环和WinMain函数

    QT源码解析(一) QT创建窗口程序.消息循环和WinMain函数 分类: QT2009-10-28 13:33 17695人阅读 评论(13) 收藏 举报 qtapplicationwindowse ...

  3. Eclipse项目和MyEclipse项目

    因为Eclipse的项目结构和MyEclipse项目的结构不同,所以两者的项目之间不能直接运行的. 我们在创建Eclipse项目的时候可以进行一些设置,这样在Eclipse中创建的项目可以直接在MyE ...

  4. EJB--事务管理 .

    在我们对事务的基本概念以及出现的问题和隔离级别有进一步的了解之后,接下来看看EJB是如何进行事务管理. 在EJB中有两种使用事务的方式.第一种方式通过容器管理的事务,叫CMT(Container-Ma ...

  5. 转TerreyLee AJAX入门系列2——ScriptManager的理解总结

    ScriptManager的功能之一就是处理页面上局部更新,对于这点,我想大家都知道.但是他工作的原理到底是什么呢,这个暂且不从正面来回答. 我们这样想一下,目前能够真正实现局部刷新的就是js+xml ...

  6. float与double的范围和精度

    1. 范围   float和double的范围是由指数的位数来决定的.  float的指数位有8位,而double的指数位有11位,分布如下:  float:  1bit(符号位) 8bits(指数位 ...

  7. PHP程序员最常犯的11个MySQL错误

    对于大多数web应用来说,数据库都是一个十分基础性的部分.如果你在使用PHP,那么你很可能也在使用MySQL—LAMP系列中举足轻重的一份子. 对于很多新手们来说,使用PHP可以在短短几个小时之内轻松 ...

  8. 一些非常有用的html,css,javascript代码片段(持久更新)

    1.判断设备是否联网 if (navigator.onLine) { //some code }else{ //others code } 2.获取url的指定参数 function getStrin ...

  9. A06_RelativeLayout的属性设置

    设有两个控件one和two,以控件one为基准.由于代码比较简单就不贴了,直接上效果图. 一.第一组:将控件two放在控件one的上.下.左.右.开始.结束. android:layout_below ...

  10. UVa 10054 The Necklace【欧拉回路】

    题意:给出n个珠子,珠子颜色分为两半,分别用1到50之间的数字表示, 现在给出n个珠子分别的颜色,问是否能够串成一个环.即为首尾相连,成为一个回路 判断是否构成一个环,即判断是否为欧拉回路,只需要判断 ...