洛谷 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. JEET W1S运动蓝牙耳机简评

    对于我这种喜欢运动的人来说,很早之前就一直想买个运动蓝牙耳机了.这次正好有此机会可以评测来自JEET的W1S运动蓝牙耳机,真的是非常的幸运! 终于,在期盼中,我的来自深圳的快递隔了四天终于到了!JEE ...

  2. mybatis常用功能总结

    mybatis-plus常用功能总结-以User表为例 1.数据库 id name age email create_time update_time version deleted 1 mary 2 ...

  3. ArrayList初步使用

    ️Practice the usage of ArrayList all of String with a exampe of NoteBook. ArrayList all of String的部分 ...

  4. Gentoo 后的几个细节的完善

    Gentoo 后的几个细节的完善 目录 Gentoo 后的几个细节的完善 细节一:引导分区与 cdrom 开机正确挂载 细节二:可预见的命名规则的网络接口名称改为传统的 eth0 细节三:为管理员用户 ...

  5. Pytorch实现对卷积的可插拔reparameterization

    需要实现对卷积层的重参数化reparameterization 但是代码里卷积前weight并没有hook,很难在原本的卷积类上用pure oo的方式实现 目前的解决方案是继承原本的卷积,挂载一个we ...

  6. Java7中Switch为什么只支持byte、short、char、int、String

    Java 7中,switch的参数可以是String类型了,这对我们来说是一个很方便的改进.到目前为止switch支持这样几种数据类型:byte short int char String .但是,作 ...

  7. ES6学习-0 前言

    本菜鸟做了二十来年的程序开发了,前后台都写过,队伍也带过.大约是2000年左右,是用dephi 写后台CGI,所有的html,js,css基本都是混在CGI里输出到前台的,那时也没有明确的前后台的概念 ...

  8. C#类中方法的执行顺序

    有些中级开发小伙伴还是搞不太明白在继承父类以及不同场景实例化的情况下,父类和子类的各种方法的执行顺序到底是什么,下面通过场景的举例来重新认识下方法的执行顺序: (下面内容涉及到了C#中的继承,构造函数 ...

  9. [bug] C:error: initializer element is not constant

    参考 http://codingdict.com/questions/45121

  10. [bug] Springboot JPA使用Sort排序时的问题

    参考 https://blog.csdn.net/qq_44039966/article/details/102713779