题目传送门

  传送点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. cocos2d JS-(JavaScript) cc.each循环遍历对象

    有了它,妈妈再也不用担心我的数组会越界啦!! each()方法能使DOM循环结构简洁,不容易出错.each()函数封装了十分强大的遍历功能,使用也很方便,它可以遍历一维数组.多维数组.DOM, JSO ...

  2. unity3d-角色控制器续

    自学是一个坚持和寂寞的过程,写博客更是一个总结与成长的过程,加油! 角色控制器续 之前学习了角色漫游,但里面有很多效果都不是我想要的.只有自己的动手实践了才能理会其中的奥妙.所以我又琢磨了许久. 为了 ...

  3. Hadoop.之.入门部署

    一.课程目标 ->大数据是什么?大数据能做什么? ->什么是Hadoop?Hadoop的设计思想? ->Hadoop如何解决大数据的问题?(什么是hdfs与yarn.MapReduc ...

  4. 010-判断是否回传IsPostBack属性

    属性IsPostBack:判断是否回传 如果是第一次请求,则返回false 如果是回传请求,则返回true->说明:只有使用服务器端表单才可以正常使用IsPostBack->使用情境:当在 ...

  5. programmatically detect whenever test run is in debug mode

    if (System.Diagnostics.Debugger.IsAttached)    // code or timeout value when running tests in debug ...

  6. hbase-java-api003(put list)

    package api; import java.io.IOException; import java.util.ArrayList; import java.util.List; import o ...

  7. Lua 可变参数之arg与select

    function TestFunc(...) local arg = { ... } --Lua .2以后不再支持默认arg参数,{}与...之间要有空格 print("输入的参数个数:&q ...

  8. Vue系列之 => 自定义全局指定让文本框自动获取焦点

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. 认识ZTree

    ZTree基本知识 zTree 是一个依靠 jQuery 实现的多功能 “树插件”.优异的性能.灵活的配置.多种功能的组合是 zTree 最大优点. 一.最简单的树(标准的json数据): 1.set ...

  10. 回声状态网络(ESN)基础教程

    http://jlearning.cn/2017/05/29/ESN-basic-tutorial/ 最近在看回声状态网络(Echo State Network)的内容,注意到中文搜索引擎搜不到关于有 ...