【题解】【洛谷 P1967】 货车运输
洛谷 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】 货车运输的更多相关文章
- 洛谷 P1967 货车运输
洛谷 P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在 ...
- 洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增
倍增lca板子洛谷P3379 #include<cstdio> struct E { int to,next; }e[]; ],anc[][],log2n,deep[],n,m,s,ne; ...
- 【杂题总汇】NOIP2013(洛谷P1967) 货车运输
[洛谷P1967] 货车运输 重做NOIP提高组ing... +传送门-洛谷P1967+ ◇ 题目(copy from 洛谷) 题目描述 A国有n座城市,编号从1到n,城市之间有m条双向道路.每一条道 ...
- 洛谷 P1967 货车运输(克鲁斯卡尔重构树)
题目描述 AAA国有nn n座城市,编号从 11 1到n nn,城市之间有 mmm 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 qqq 辆货车在运输货物, 司机们想知道每辆车在不超过车 ...
- 洛谷 P1967 货车运输 Label: 倍增LCA && 最小瓶颈路
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- 洛谷P1967 货车运输
题目描述 \(A\)国有\(n\)座城市,编号从\(1\)到\(n\),城市之间有\(m\)条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有\(q\)辆货车在运输货物, 司机们想知道每辆车在 ...
- [NOIP2013] 提高组 洛谷P1967 货车运输
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- [洛谷 P1967] 货车运输 (最大生成树 lca)
题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多 ...
- 洛谷—— P1967 货车运输 || COGS——C 1439. [NOIP2013]货车运输
https://www.luogu.org/problem/show?pid=1967#sub || http://www.cogs.pro/cogs/problem/problem.php?pi ...
- NOIP 2013 提高组 洛谷P1967 货车运输 (Kruskal重构树)
题目: A 国有 nn 座城市,编号从 11 到 nn,城市之间有 mm 条双向道路.每一条道路对车辆都有重量限制,简称限重. 现在有 qq 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情 ...
随机推荐
- Cauchy-Binet 公式的应用
Binet-Cauchy 公式 我们知道,方阵的行列式不是方阵的线性函数,即对 \(\forall \lambda\in F,A,B\in F^{n\times n}\),有 \(det(A+B)\n ...
- 云空调来自 GitHub 的冷气——GitHub 热点速览 v.21.20
作者:HelloGitHub-小鱼干 万物皆可上云,air-conditioner 是上周火爆小鱼干朋友圈和公众号信息流的云空调项目.第一眼的时候,你会觉得和这个云空调还挺别致的,第二眼,si~~感到 ...
- mysql unique key
create table b1(id int,name char unique)这样name字段就唯一了 或者create table b1(id int,name char,unique(id),u ...
- 【Cocos2d-x】屏蔽Emoji并解决由于Emoji导致的崩溃问题
IOS的Emoji表情因为编码问题,在Android手机上无法正常显示,如果当前的cc.Label节点使用的是系统字,在系统字库中找不到对应编码的字符,会导致崩溃. 为了解决这个问题,又要兼顾新老版本 ...
- 使用 yum-cron 自动更新 Linux系统
使用 yum-cron 自动更新 Linux系统 Linux系统技术交流QQ群(1675603)验证问题答案:刘遄 我知道如何使用 yum 命令行 更新系统,但是我想用 cron 任务自动更新软件 ...
- git 速度慢问题解决
使用VPN上网后,如果git下载速度还是很慢说明没有正确设置代理 查看你的代理模式是否是pac代理,如果是改成全局或者Http代理,pac代理会选择性的代理网站,可能会略过某些网站. 如果还是比较慢则 ...
- MyBatis 动态 SQL 语句中出现 '<' 的问题
问题描述 映射接口方法如下: /** * 根据姓名和年龄查询用户信息 * @param name 姓名 * @param user 获取年龄 * @return */ public List<U ...
- 4 系统的 CPU 使用率很高,但为啥却找不到高 CPU的应用?
上一节讲了 CPU 使用率是什么,并通过一个案例教你使用 top.vmstat.pidstat 等工具,排查高 CPU 使用率的进程,然后再使用 perf top 工具,定位应用内部函数的问题.不过就 ...
- esp项目,
http://www.cirmall.com/circuit/6012/%E6%99%BA%E8%83%BD%E5%8C%96%E7%A7%8D%E8%8A%B1%E7%AE%80%E6%98%93% ...
- 服务器RAID配置
一.RAID介绍RAID是Redundent Array of Inexpensive Disks的缩写,直译为"廉价冗余磁盘阵列",也简称为"磁盘阵列".后来 ...