【题目链接】

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. 几种USB控制器类型:OHCI,UHCI,EHCI,xHCI

    http://smilejay.com/2012/10/usb_controller_xhci/ 遇到过一些关于USB的东西(如下),一直没搞明白什么USB1.0/1.1/2.0/3.0之类的,当然我 ...

  2. s3cmd的安装与使用

     s3cmd 是一款 Amazon S3 命令行工具.它不仅能上传.下载.同步,还能设置权限,下面是完整的安装使用指南. 主要是还是用来储存日志文件或者其他什么资料. https://wangyan. ...

  3. java:构造函数

    class Dog { Dog(){ } } 构造函数没有返回值定义,构造函数名必须和类名相同,如果类里面没有构造函数,编译器会帮你加一个构造函数. 使用this调用构造函数 class Dog { ...

  4. lua的split函数

    function split(s, delim) then return end local t = {} while true do local pos = string.find (s, deli ...

  5. Unified Emoji表情for Android

    这个是我做Android以来碰到的最烦的东西,该死的emoji表情,恨之入骨..无奈这个问题分配给我了.我也只能硬着头皮做. 0.吐个槽先 首先,你要明白什么是emoji表情,不知道的google,不 ...

  6. (转)Spring的编程式事务例子

    纯JDBC操作, 对某些项目来说, 也许更好, Spring JDBC Framework让你不用关心Connection, Statement, ResultSet. 定义数据源 spring事务编 ...

  7. PHP大神的十大优良习惯

    概述:通往PHP大神的道路上,应该保持优良的传统和习惯. 1.多阅读手册和源代码 没什么比阅读手册更值得强调的事了–仅仅通过阅读手册你就可以学习到很多东西,特别是很多有关于字符串和数组的函数.就在这些 ...

  8. java类的加载以及初始化顺序

    类的加载和初始化的了解对于我们对编程的理解有很大帮助,最近在看类的记载方面的问题.从网上查阅了若干文章,现总结如下: 我们通过一段代码来了解类加载和初始化的顺序: package com.classl ...

  9. WCF学习笔记之地址

    1.统一资源标识(URI) URI全称是Uniform Resource Identifier(统一资源标识),唯一地标识一个网络资源的同时也标识资源所处的位置以及访问方式(资源访问所用的网络协议). ...

  10. java中的线程创建和使用

    Java中实现多线程有两种途径:继承Thread类或者实现Runnable接口.Runnable是接口,建议用接口的方式生成线程,因为接口可以实现多继承,况且Runnable只有一个run方法,很适合 ...