传送门

这道题,先用kruskal求一遍图中的最大生成树。

然后,倍增求lca,求lca的同时求出边权的最小值。

#include <cstring>
#include <cstdio>
#include <algorithm> int n, m, cnt, q, t, k;
int f[], head[], p[][], minn[][], deep[];
bool vis[];
struct node
{
int x, y, z;
}tree[];
struct Node
{
int next, to, val;
}edge[]; inline void add(int a, int b, int c)
{
edge[cnt].val = c;
edge[cnt].to = b;
edge[cnt].next = head[a];
head[a] = cnt++;
} inline int father(int a)
{
return a == f[a] ? a : f[a] = father(f[a]);
} inline bool cmp(node a, node b)
{
return a.z > b.z;
} void kruskal()
{
int i;
for(i = ; i <= m; i++) scanf("%d %d %d", &tree[i].x, &tree[i].y, &tree[i].z);
for(i = ; i <= n; i++) f[i] = i;
std::sort(tree + , tree + m + , cmp);
for(i = ; i <= m; i++)
{
int fa = father(tree[i].x), fb = father(tree[i].y);
if(fa != fb)
{
f[fa] = fb;
add(tree[i].x, tree[i].y, tree[i].z);
add(tree[i].y, tree[i].x, tree[i].z);
}
if(k == n - ) break;
}
} void dfs(int i)
{
int j;
vis[i] = ;
for(j = head[i]; j != -; j = edge[j].next)
if(!vis[edge[j].to])
{
deep[edge[j].to] = deep[i] + ;
p[edge[j].to][] = i;
minn[edge[j].to][] = edge[j].val;
dfs(edge[j].to);
}
} void init()
{
int i, j;
for(j = ; ( << j) <= n; j++)
for(i = ; i <= n; i++)
{
p[i][j] = p[p[i][j - ]][j - ];
minn[i][j] = std::min(minn[i][j - ], minn[p[i][j - ]][j - ]);
}
} int lca(int a, int b)
{
int i, j, ret = ;
if(deep[a] < deep[b]) std::swap(a, b);
for(i = ; ( << i) <= deep[a]; i++);
i--;
for(j = i; j >= ; j--)
if(deep[a] - ( << j) >= deep[b])
{
ret = std::min(ret, minn[a][j]);
a = p[a][j];
}
if(a == b) return ret;
for(j = i; j >= ; j--)
if(p[a][j] != p[b][j])
{
ret = std::min(ret, std::min(minn[a][j], minn[b][j]));
a = p[a][j];
b = p[b][j];
}
ret = std::min(ret, std::min(minn[a][], minn[b][]));
return ret;
} int main()
{
int i, j, x1, y1;
scanf("%d %d", &n, &m);
memset(head, -, sizeof(head));
//memset(minn, 127 / 3, sizeof(minn));
kruskal();
for(i = ; i <= n; i++)
if(!vis[i])
{
deep[i] = ;
dfs(i);
}
init();
scanf("%d", &q);
for(i = ; i <= q; i++)
{
scanf("%d %d", &x1, &y1);
if(father(x1) != father(y1)) printf("-1\n");
else printf("%d\n", lca(x1, y1));
}
return ; }

换了写法

惨啊,

i >= 0 我居然nc的用 i 代替

应该是 i >= 1 用 i 代替

 #include <cstdio>
#include <cstring>
#include <algorithm> const int MAXN = , MAXM = , INF = ;
int n, m, q, cnt, tot;
int head[MAXM], to[MAXM << ], next[MAXM << ], val[MAXM << ];
int f1[MAXN], f[MAXN][], min[MAXN][], deep[MAXN]; struct node
{
int x, y, z;
}p[MAXM]; inline bool cmp(node a, node b)
{
return a.z > b.z;
} inline void add(int x, int y, int z)
{
to[cnt] = y;
val[cnt] = z;
next[cnt] = head[x];
head[x] = cnt++;
} inline int find(int x)
{
return x == f1[x] ? x : f1[x] = find(f1[x]);
} inline int Min(int x, int y)
{
return x < y ? x : y;
} inline void swap(int &x, int &y)
{
x ^= y ^= x ^= y;
} inline void dfs(int u)
{
int i, v;
deep[u] = deep[f[u][]] + ;
for(i = ; f[u][i]; i++)
f[u][i + ] = f[f[u][i]][i],
min[u][i + ] = Min(min[u][i], min[f[u][i]][i]);
for(i = head[u]; i ^ -; i = next[i])
{
v = to[i];
if(!deep[v])
{
f[v][] = u;
min[v][] = val[i];
dfs(v);
}
}
} inline int lca(int x, int y)
{
int i, ans = INF;
if(deep[x] < deep[y]) swap(x, y);
for(i = ; i >= ; i--)
if(deep[f[x][i]] >= deep[y])
ans = Min(ans, min[x][i]), x = f[x][i];
if(x == y) return ans == INF ? - : ans;
for(i = ; i >= ; i--)
if(f[x][i] ^ f[y][i])
ans = Min(ans, min[x][i]),
ans = Min(ans, min[y][i]),
x = f[x][i], y = f[y][i];
ans = Min(ans, min[x][]);
ans = Min(ans, min[y][]);
return ans == INF ? - : ans;
} int main()
{
//freopen("truck.in", "r", stdin);
//freopen("truck.out", "w", stdout);
int i, x, y, fx, fy;
scanf("%d %d", &n, &m);
memset(head, -, sizeof(head));
memset(min, / , sizeof(min));
for(i = ; i <= m; i++) scanf("%d %d %d", &p[i].x, &p[i].y, &p[i].z);
std::sort(p + , p + m + , cmp);
for(i = ; i <= n; i++) f1[i] = i;
for(i = ; i <= m; i++)
{
fx = find(p[i].x);
fy = find(p[i].y);
if(fx ^ fy)
{
f1[fx] = fy;
tot++;
add(p[i].x, p[i].y, p[i].z);
add(p[i].y, p[i].x, p[i].z);
}
if(tot == n - ) break;
}
for(i = ; i <= n; i++)
if(!deep[i])
dfs(i);
scanf("%d", &q);
for(i = ; i <= q; i++)
{
scanf("%d %d", &x, &y);
if(find(x) ^ find(y)) puts("-1");
else printf("%d\n", lca(x, y));
}
return ;
}

NOIP2013D1T3货车运输(最大生成树+倍增lca)的更多相关文章

  1. TZOJ 4848 货车运输(最大生成树+倍增lca)

    描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多 ...

  2. $Noip2013/Luogu1967$ 货车运输 最大生成树+倍增$lca$

    $Luogu$ $Sol$ 首先当然是构建一棵最大生成树,然后对于一辆货车的起点和终点倍增跑$lca$更新答案就好.记得预处理倍增的时候不仅要处理走了$2^i$步后是那个点,还有这中间经过的路径权值的 ...

  3. 【NOIP2013】货车运输 最大生成树+倍增

    题目大意:给你一张n个点m条边的图,有q次询问,每次让你找出一条从x至y的路径,使得路径上经过的边的最小值最大,输出这个最大的最小值. 显然,经过的路径必然在这张图的最大生成树上. 我们求出这个图的最 ...

  4. 「NOIP2013」「LuoguP1967」货车运输(最大生成树 倍增 LCA

    题目描述 AA国有nn座城市,编号从 11到nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最 ...

  5. 货车运输(最大生成树+倍增LCA)

    看到第一篇题解的神奇码风--我决定发一篇码风正常的题解造福人类 这题的做法也非常经典,最大生成树\(+LCA\),相当于先贪心一下,在LCA的时候记录一下当前最小的边权 顺便吐槽一下最后一个测试点: ...

  6. 【洛谷1967】货车运输(最大生成树+倍增LCA)

    点此看题面 大致题意: 有\(n\)个城市和\(m\)条道路,每条道路有一个限重.多组询问,每次询问从\(x\)到\(y\)的最大载重为多少. 一个贪心的想法 首先,让我们来贪心一波. 由于要求最大载 ...

  7. 货车运输 noip2013 luogu P1967 (最大生成树+倍增LCA)

    luogu题目传送门! 首先,题目让我们求每个货车的最大运输量,翻译一下就是求路径上边权最小的边. 利用一下贪心思想可知,所有货车肯定都会尽量往大的边走. 进一步翻译,即为有一些小边货车根本不会走,或 ...

  8. 【NOIP2013】货车运输 最大生成树+LCA

    题目描述 AA国有nn座城市,编号从 1到n,城市之间有m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重 ...

  9. Luogu1967 NOIP2013 货车运输 最大生成树、倍增

    传送门 题意:给出一个$N$个节点.$M$条边的图,$Q$次询问,每一次询问两个点之间的所有可行路径中经过的边的边权的最小值中的最大值.$N \leq 10000 , M \leq 50000 , Q ...

随机推荐

  1. input标签属性

    很多时候,我们都用到了很多标签实现输入功能,所以在这里梳理一下. 1.建立一个文本框 <input type="text" name="userName" ...

  2. jQuery选择器之基本筛选选择器

    <h2>基本筛选器</h2> <h3>:first/:last/:even/:odd</h3> <div class="left&quo ...

  3. 谈谈对Android中的消息机制的理解

    Android中的消息机制主要由Handler.MessageQueue.Looper三个类组成,他们的主要作用是 Handler负责发送.处理Message MessageQueue负责维护Mess ...

  4. C# 调用第三方DLL缓冲区溢出导致的异常

    这个倒是少见的错误,纪录一下大佬. 先上异常 错误一:尝试读取或写入受保护的内存 错误二:未将对象引用设置到对象的实例 错误三:  托管调试助手“FatalExecutionEngineError”( ...

  5. IOS OS X 中集中消息的传递机制

    1 KVO (key-value Observing) 是提供对象属性被改变是的通知机制.KVO的实现实在Foundation中,很多基于 Foundation 的框架都依赖与它.如果只对某一个对象的 ...

  6. php bz2扩展安装

    php bz2扩展安装 2017年09月22日 14:14:36 Cookie_1030 阅读数:1781   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn ...

  7. Linux之 if命令——简单的shell文件

    如何写一个shell文件,写一个小脚本 1.新建一个脚本文件:vi demo.sh 2.追加执行权限: chmod u+x demo.sh 3.执行脚本:./demo.sh 4.什么是脚本?把一堆命令 ...

  8. golang结构体排序 - 根据下载时间重命名本地文件

    喜M拉Y下载音频到手机,使用ximalaya.exe 解密[.x2m]为[.m4a]根据文件下载创建时间,顺序重命名文件,方便后续播放. 源码如下:package main import ( &quo ...

  9. docker client和daemom

    client 模式 docker命令对应的源文件是docker/docker.go, docker [options] command [arg...] 其中options参数为flag,任何时候执行 ...

  10. Hbase数据库简介

    Hbase是基于Hadoop下分布式存储 数据库,列式存储.(https://www.imooc.com/video/17202) 动态的增加列,不像关系数据库需要提前定义好列. 关系数据库     ...