题目传送门

  传送点I

  传送点II

题目大意

  给定一个有$n$个点$m$条边的图,每个点有一个高度$h_{i}$,能从$u$经过一条边到达$v$,当且仅当存在一条边是$(u, v)$或$(v, u)$,且$h_{u}\geqslant h_{v}$。问1号点能到达的所有点的最小树形图的边权和。

  第一问沙雕问题。直接一个搜索水过。

  第二问,好像是最小树形图。看着数据范围,嗯,别想朱-刘了。

  感觉可以直接Prim。于是愉快地WA了一发。来回顾一下Prim算法的正确性证明

可以不妨设图中所有边的权重都不同,这样最小生成树是唯一的

设Prim算法得到$G$,而最小生成树是$T$。考虑用反证法。

设在生成G的过程中第一次产生的不在T中的边是$e$,未加入$e$时的点集为$V$。

把$e$加入$T$之后会出现环,这个环内必然存在一条边$f = (u, v) \neq e$使得$u\in V, v\notin V$(因为$e$的一个端点不在$V$中)。由Prim的贪心策略可知$w(e) < w(f)$。用$e$替换掉$f$可以得到更优的生成树,这与最小生成树矛盾。因此$T = G$。

  但树形图不像树那么简单。如果尝试用这种方法去证明可以发现需要讨论两条边的方向,于是很轻松就能卡掉这个zz做法。

  然后如何hack这个zz做法呢?

  于是这个假做法跑出了497的优秀答案。

  好了好了,开始说正题。

  因为不能用朱-刘算法,考虑这样的图有什么样的性质。

  把通过双向边连通的点缩起来。这样剩一个DAG。

  考虑对于一个被缩起来的一块,它自己相当于一个无向图,可以用最小生成树的算法。

  对于连向这个块的出边,它们选还是不选入树形图只对这个块中的选边有影响。

  因此可以将前面的块都看成一个点。然后很有趣的事情来了,直接把这些有向边看成无向边,然后上MST算法。

  为什么这样做是对的。因为我们可以将任意一个树形图映射成一个边权和与它相等的生成树或者一个生成树映射成一个边权和与它相等的树形图。

  做法很简单。前一部分直接将有向边看成无向边,后一部分从 "前面的块都看成一个点" 指的点开始沿着树边bfs,这样就可以定向了。

  具体实现不用将前面的块缩起来。直接以结束点的高度为第一关键字,边权为第二关键字排序即可。

  (虽然我很好奇为什么大家都写Kruskal。显然写Prim可以少写点东西)

Code

 /**
* bzoj
* Problem#
* Accepted
* Time: 13128ms
* Memory: 53364k
*/
#include <bits/stdc++.h>
#ifndef WIN32
#define Auto "%lld"
#else
#define Auto "%I64d"
#endif
using namespace std;
typedef bool boolean; typedef class Edge {
public:
int ed, w; Edge() { }
Edge(int ed, int w):ed(ed), w(w) { }
}Edge; int n, m;
int *hs;
boolean* added;
vector<Edge> *g; boolean operator < (const Edge& a, const Edge& b) {
if (hs[a.ed] ^ hs[b.ed]) return hs[a.ed] < hs[b.ed];
return a.w > b.w;
} inline void init() {
scanf("%d%d", &n, &m);
hs = new int[(n + )];
added = new boolean[(n + )];
g = new vector<Edge>[(n + )];
memset(added, false, sizeof(boolean) * (n + ));
for (int i = ; i <= n; i++)
scanf("%d", hs + i);
for (int i = , u, v, w; i <= m; i++) {
scanf("%d%d%d", &u, &v, &w);
if (hs[u] >= hs[v])
g[u].push_back(Edge(v, w));
if (hs[u] <= hs[v])
g[v].push_back(Edge(u, w));
}
} int rc = ;
long long rv = ;
priority_queue<Edge> que;
inline void solve() {
added[] = true;
for (int i = ; i < (signed) g[].size(); i++)
que.push(g[][i]);
while (!que.empty()) {
while (!que.empty() && added[que.top().ed])
que.pop();
if (que.empty())
break;
Edge e = que.top();
que.pop();
added[e.ed] = true, rc++, rv += e.w;
for (int i = ; i < (signed) g[e.ed].size(); i++)
que.push(g[e.ed][i]);
}
printf("%d "Auto, rc, rv);
} int main() {
init();
solve();
return ;
}

bzoj 2753 [SCOI 2012] 滑雪与时间胶囊 - Prim的更多相关文章

  1. [SCOI 2012]滑雪与时间胶囊

    Description a180285非常喜欢滑雪.他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi. ...

  2. BZOJ 2754 SCOI 2012 喵星球上的点名 后缀数组 树状数组

    2754: [SCOI2012]喵星球上的点名 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2068  Solved: 907[Submit][St ...

  3. 【最小树形图(奇怪的kruskal)】【SCOI 2012】【bzoj 2753】滑雪与时间胶囊

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 1621 Solved: 570 Description ...

  4. 【BZOJ】【2753】【SCOI2012】滑雪与时间胶囊

    Kruskal/最小树形图 然而蒟蒻并不会做这题>_> 本来以为是有向图最小生成树,即最小树形图,但这数据范围有点…… 膜拜了zyf的题解:http://www.cnblogs.com/z ...

  5. BZOJ 2753 [SCOI2012] 滑雪和时间胶囊 最小生成树

    题目链接: 题目 2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB 问题描述 a180285非常喜欢滑雪.他来到一座雪山, ...

  6. bzoj 2753: [SCOI2012]滑雪与时间胶囊 -- 最小生成树

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MB Description a180285非常喜欢滑雪.他来到一座雪山,这 ...

  7. CDOJ 42/BZOJ 2753 滑雪与时间胶囊 kruskal

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1376  Solved: 487[Submit][St ...

  8. 【BZOJ 2753】 2753: [SCOI2012]滑雪与时间胶囊 (分层最小树形图,MST)

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2457  Solved: 859 Descriptio ...

  9. 2753: [SCOI2012]滑雪与时间胶囊

    2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2633  Solved: 910 Descriptio ...

随机推荐

  1. VUE中过了一遍还不熟悉的东西

    1.computed/watch/和methods computed是依赖于数据来变动的,有缓存,当不需要缓存的时候就用方法,watch不建议乱用,当有异步请求的时候就用watch 写法一样 2.wa ...

  2. pytorch进行图像分类的流程,下一篇为实例源代码解析

    一.预处理部分 1.拿到数据首先对数据进行分析 对数据的分布有一个大致的了解,可以用画图函数查看所有类的分布情况.可以采取删除不合理类的方法来提高准确率: 对图像进行分析,在自定义的图像增强的多种方式 ...

  3. js跨域需要token。

    将rems从tms中独立出来以后,每次都需要先打开tms,再打开rems,如果我足够聪明,那么很容易可以分析得到原因. 第一,会导致跨域出现问题的易错点就那么几个,是否加上“Access-Contro ...

  4. 14. Longest Common Prefix(暴力循环)

    Write a function to find the longest common prefix string amongst an array of strings. If there is n ...

  5. Linux 查看磁盘或文件夹及文件大小

    当磁盘大小超过标准时会有报警提示,这时如果掌握df和du命令是非常明智的选择. df可以查看一级文件夹大小.使用比例.档案系统及其挂入点,但对文件却无能为力.    du可以查看文件及文件夹的大小. ...

  6. html5-css综合练习

    div{    width: 600px;    height: 800px;    padding: 40px;    font-size: 12px;    line-height: 25px;  ...

  7. Codeforces Round #323

    div1 C 这题的是给了一个无限循环的子数组,问有多少个 (l,s)l代表起点s代表长度的循环串,使得所有的在原串中的每位都小于等于另外这个串(l<=n,1<=s<n) 像这样,我 ...

  8. 多线程实现Thread.Start()与ThreadPool.QueueUserWorkItem两种方式对比

    Thread.Start(),ThreadPool.QueueUserWorkItem都是在实现多线程并行编程时常用的方法.两种方式有何异同点,而又该如何取舍? 写一个Demo,分别用两种方式实现.观 ...

  9. sql server 将两列的值合并到另一列

    select top 100 t2.FullName, * from Subject,(select id, isnull(first_name,'') +isnull(middle_name,'') ...

  10. IOS 开发体验测试问题

    1.键盘收起体验 a. 文本键盘会收起,但是表情包.添加视频的键盘不会收起: b. 在会话场景中,同时进行一个点击输入框,一个向下滑,输入框中的聚焦的竖直细线不会消失: