洛谷 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. Win10 ntoskrnl.exe蓝屏解决

    主机一直用的是无线网卡,装Win10下载驱动.不管是Window10自己更新,还是通过驱动人生.驱动精灵等安装的Killer网卡驱动,均日常导致蓝屏. 状态是这样的:玩游戏蓝屏.检测系统蓝屏.清垃圾蓝 ...

  2. unresolved external symbol _WinMain@16

    vc下,新建一个win32项目,就写了个main函数,打印hello ,出现了如标题所述的错误 原因: 你建立了一个WINDOWS应用程序,可是你却在入口函数的时候使用main而不是WinMain 解 ...

  3. 一文带你详细介绍c++中的std::move函数

    前言 在探讨c++11中的Move函数前,先介绍两个概念(左值和右值) 左值和右值 首先区分左值和右值 左值是表达式结束后依然存在的持久对象(代表一个在内存中占有确定位置的对象) 右值是表达式结束时不 ...

  4. BUAA软件工程热身作业

    写在前面 项目 内容 所属课程 2020春季计算机学院软件工程(罗杰 任健) (北航) 作业要求 热身作业(阅读) 课程目标 培养软件开发能力 本作业对实现目标的具体作用 深入认识自己,总结过往并展望 ...

  5. 【BUAA软工】团队项目选择

    项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:团队项目选择与NABCD分析 团队项目选择 项目介绍 项目简介 项目名称:Visual Lab Online 项目简介:一款面向学生和个 ...

  6. CRM帮助B2B企业持续改善战略决策「上篇」

    数据一直都是企业和客户的热点话题.客户期望得到更加个性化的感受,企业则期望使用数据来持续改善战略决策和给予更好的服务 B2B企业如何更合理地利用客户资料: 数据采集 长期以来,B2C行业的企业都是通过 ...

  7. 1Spring注入小结

    Spring注入小结 (在Application.xml中) Spring学习笔记 周芋杉2021/5/14 1.基本注入类型注入 注入前的准备 <bean id="#配置文件的唯一标 ...

  8. 把el-element的日期格式改为CRON

    在日常的开发当中,经常会遇到格式的不匹配造成的困扰. 在日期管理上,el-element也是贴心的准备了相关的日期选择器,但是在取值的时候发现,el-element所给出的值格式可能并不是我们常用的. ...

  9. top,它们的意思分别是1分钟、5分钟、15分钟内系统的平均负荷。

    理解Linux系统负荷   作者: 阮一峰 日期: 2011年7月31日   一.查看系统负荷 如果你的电脑很慢,你或许想查看一下,它的工作量是否太大了. 在Linux系统中,我们一般使用uptime ...

  10. WPS2019党政机关单位版(无广告困扰)

    WPS2019党政机关单位版(无广告困扰) 科技趣闻 ​ 中国石油大学(华东) 控制科学与工程硕士 17 人赞同了该文章 导读 WPS Office 2019专业版机关版是由WPS官方专为企业.机关单 ...