洛谷 P1967 货车运输


原题

题面请查看洛谷 P1967 货车运输


题解

思路

根据题面,假设我们有一个普通的图:

作图工具:Graph Editor

考虑从顶点\(1\)走到顶点\(3\):

  • 路径\(1 \to 3\)(最大运货量为\(1\));

  • 路径\(1 \to 2 \to 3\)(最大运货量为\(3\),更优)。

所以我们可以删掉\(1 \to 3\)这条边,形成了一棵树,通过多次观察发现,这是一颗原图的最大生成树

问题就被转化成了求最大生成树在树上解决原问题

代码

  • 求最大生成树:我们使用\(\text{Kruskal}\)算法;

  • 在树上解决原问题比较简单,我们只需要通过最近公共祖先(倍增法求解)进行求解即可。

代码如下:

#include <algorithm>
#include <cstdio>
using std::sort;
#define INF 0X3F3F3F3F
#define min(a, b) ((a) < (b) ? (a) : (b)) struct Tree
{
bool vis[10001];
int cnt, head[10001], to[20001], w[20001], Next[20001];
int dep[10001], fa[10001][21], W[10001][21];
void DFS(int);
void Add_Edge(int, int, int);
void LCA_Init(void);
int LCA(int, int);
}; struct Graph
{
struct Kruskal
{
struct Edge
{
int f, t, val;
bool operator<(const Edge &a) const
{
return val > a.val;
}
}; struct Union_Find
{
int ID[10001]; void Init(void);
void connect(int, int);
bool search(int, int);
int find(int);
}; Union_Find B;
Edge E[50001]; void kruskal(void);
}; int n, m;
Kruskal K; void Read(void);
}; int q;
Tree T;
Graph G; int main(void)
{
G.Read();
G.K.B.Init();
G.K.kruskal();
T.LCA_Init();
scanf("%d", &q);
while (q--)
{
static int x, y;
scanf("%d%d", &x, &y);
printf("%d\n", T.LCA(x, y));
} return 0;
} void Tree::Add_Edge(int f, int t, int val)
{
Next[++cnt] = head[f];
to[cnt] = t;
w[cnt] = val;
head[f] = cnt;
return;
} void Tree::DFS(int ID)
{
register int i, To;
vis[ID] = true;
for (i = head[ID]; i; i = Next[i])
{
To = to[i];
if (vis[To])
continue;
dep[To] = dep[ID] + 1;
fa[To][0] = ID;
W[To][0] = w[i];
DFS(To);
}
return;
} void Tree::LCA_Init(void)
{
register int i, j;
for (i = 1; i <= G.n; ++i)
if (!vis[i])
{
dep[i] = 1;
DFS(i);
fa[i][0] = i;
W[i][0] = INF;
}
for (i = 1; i <= 20; ++i)
for (j = 1; j <= G.n; ++j)
{
fa[j][i] = fa[fa[j][i - 1]][i - 1];
W[j][i] = min(W[j][i - 1], W[fa[j][i - 1]][i - 1]);
}
return;
} int Tree::LCA(int x, int y)
{
if (!G.K.B.search(x, y))
return -1;
register int i, ans = INF;
if (dep[x] > dep[y])
{
int temp = x;
x = y;
y = temp;
}
for (i = 20; i >= 0; --i)
if (dep[fa[y][i]] >= dep[x])
{
ans = min(ans, W[y][i]);
y = fa[y][i];
}
if (x == y)
return ans;
for (i = 20; i >= 0; --i)
if (fa[x][i] != fa[y][i])
{
ans = min(ans, min(W[x][i], W[y][i]));
x = fa[x][i];
y = fa[y][i];
}
ans = min(ans, min(W[x][0], W[y][0]));
return ans;
} void Graph::Kruskal::Union_Find::Init(void)
{
register int i;
for (i = 1; i <= G.n; ++i)
ID[i] = i;
return;
} void Graph::Kruskal::Union_Find::connect(int a, int b)
{
register int ra = find(a), rb = find(b);
if (ra != rb)
ID[rb] = ra;
return;
} bool Graph::Kruskal::Union_Find::search(int a, int b)
{
return find(a) == find(b);
} int Graph::Kruskal::Union_Find::find(int x)
{
if (x == ID[x])
return x;
else
return ID[x] = find(ID[x]);
} void Graph::Kruskal::kruskal(void)
{
register int i, cnt = 0;
sort(E + 1, E + G.m + 1);
for (i = 1; i <= G.m && cnt < G.n - 1; ++i)
{
if (!B.search(E[i].f, E[i].t))
{
B.connect(E[i].f, E[i].t);
++cnt;
T.Add_Edge(E[i].f, E[i].t, E[i].val);
T.Add_Edge(E[i].t, E[i].f, E[i].val);
}
}
return;
} void Graph::Read(void)
{
register int i;
scanf("%d%d", &n, &m);
for (i = 1; i <= m; ++i)
scanf("%d%d%d", &K.E[i].f, &K.E[i].t, &K.E[i].val);
return;
}

【题解】【洛谷 P1967】 货车运输的更多相关文章

  1. 洛谷 P1967 货车运输

    洛谷 P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在 ...

  2. 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

    倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...

  3. 【杂题总汇】NOIP2013(洛谷P1967) 货车运输

    [洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...

  4. 洛谷 P1967 货车运输(克鲁斯卡尔重构树)

    题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...

  5. 洛谷 P1967 货车运输 Label: 倍增LCA && 最小瓶颈路

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

  6. 洛谷P1967 货车运输

    题目描述 \(A\)国有\(n\)座城市,编号从\(1\)到\(n\),城市之间有\(m\)条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有\(q\)辆货车在运输货物, 司机们想知道每辆车在 ...

  7. [NOIP2013] 提高组 洛谷P1967 货车运输

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

  8. [洛谷 P1967] 货车运输 (最大生成树 lca)

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

  9. 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输

    https://www.luogu.org/problem/show?pid=1967#sub  ||  http://www.cogs.pro/cogs/problem/problem.php?pi ...

  10. NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)

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

随机推荐

  1. GDOI2021 游记

    蹭了个名额去参加 \(\text{GDOI}\) \(\text{tg}\),体验了一下大佬的生活/kk (以下试题皆为 \(\text A\) 卷 DAY -1 不知道要复习什么.本来没有机会来参加 ...

  2. ES6新增常用方法

    字符串新增方法 padStart.padEnd 如果原字符串不够指定长度,则会在左侧(右侧)填充字符串,用以补全 padStart( length: number, fillStr?: string ...

  3. Java安全之FastJson JdbcRowSetImpl 链分析

    Java安全之FastJson JdbcRowSetImpl 链分析 0x00 前言 续上文的Fastjson TemplatesImpl链分析,接着来学习JdbcRowSetImpl 利用链,Jdb ...

  4. .NET Worker Service 如何优雅退出

    上一篇文章中我们了解了 .NET Worker Service 的入门知识[1],今天我们接着介绍一下如何优雅地关闭和退出 Worker Service. Worker 类 从上一篇文章中,我们已经知 ...

  5. 判断标准I/O的缓冲区类型

    #include <stdio.h> void pr_stdio(const char *, FILE *); int main() { FILE *fp; fputs("ent ...

  6. 【Azure 云服务】Azure Cloud Service 创建 Alert 指南 [基于旧版 Alert(Classic)不可用情况下]

    问题描述 在Azure云服务(Cloud Service)创建Alert(Classic)时候遇见失败消息:"Failed to update alert testclassicalertr ...

  7. JAVA基础——变量、常量

    变量 java中,变量时最基本的存储单元,其要素包括变量名,变量类型和作用域. 注意事项: 每个变量都有类型,类型可以是基本类型,也可以是引用类型. 变量名必须是合法的标识符 变量声明时一条完整的语句 ...

  8. [刷题] 46 Permutations

    要求 整型数组,每个元素不相同,返回元素所有排列的可能 示例 [1,2,3] [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ] 思路 树 ...

  9. 【转载】kvm迁移

    https://www.jianshu.com/p/60132085a3c9 kvm分静态和动态迁移,静态就是关机迁移,比较简单,动态迁移就是不关闭服务器进行迁移.静态迁移:确定虚拟机关闭 https ...

  10. 【转载】有图 KVM折腾记..

    KVM折腾记...https://lengjibo.github.io/KVM%E6%8A%98%E8%85%BE%E8%AE%B0/  Veröffentlicht am 2018-09-20 |  ...