传送门

这道题,先用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. 2018微软实习笔试一道dp题目总结

    题意大概是说在一维数轴上起点和终点的距离是d,现在我们要从起点走到终点.每走一个单位长度消耗一个单位能量,初始时有K单位能量.同时在起点和终点之间分布一些加油站a1,a2,...an,给你加油站数量. ...

  2. Android Platform Version 和 API Level对照

    Platform Version API Level VERSION_CODE Notes Android 5.1 22 LOLLIPOP_MR1 Platform Highlights Androi ...

  3. http与WebSocket

    利用websocket连接服务器的最大特点就是:持久链接的特点. 共同点是:都是基于TCP协议进行client-server的链接,websocket是HTML5提出的一套补缺HTTP链接中不能持久链 ...

  4. Git理论知识补充

    转自: http://www.cnblogs.com/hnrainll/archive/2012/11/13/2768003.html 对于任何一个文件,在 Git 内都只有三种状态:已提交(comm ...

  5. 2019年今日头条机试_JAVA后台岗_第二题

    使用map的递推,java对象做key需要重写equeal,hashCode方法,使拥有相同属性值的对象被识别为同一对象. import java.util.*; class Cat{ public ...

  6. Hystrix 断路器

    断路器: 当客户端访问服务端,发现服务端有异常不能进行访问时,就会执行一个fallback 方法.

  7. .NET多线程总结

    1.不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: public void test() { ThreadStart threadStart = ...

  8. CNN完成mnist数据集手写数字识别

    # coding: utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data d ...

  9. 在虚拟机linux环境下编译windows版adb fastboot

    原文出自:http://blog.chinaunix.net/uid-20546441-id-1746200.html 我根据虚拟机编译遇到的问题进行一些添加 [前提条件] Linux Android ...

  10. 监控java进程是否正常运行

    @echo off set _task=java.exe :checkstart for /f "tokens=1" %%n in ('tasklist ^| find " ...