滑雪与时间胶囊
来源:互联网 发布:linux常用命令gcc 编辑:程序博客网 时间:2024/04/19 21:18
题目大意:
一个孩子去滑雪,他想要用最短距离访问最多景点,题目会给出M条路径和N个景点。景点是路径的交点。这个孩子还有时间胶囊,时间胶囊可以让他直接转移到上次访问过的景点,问:他从第一个点开始滑,在访问最多景点的条件下,最短路径是多少?
这道题不能用 prim 算法去做,原来 prim 是有缺陷的,它针对无向图是正确的,并不能保证有向图一定正确。
比如说
3 3
3 2 1
1 2 7
2 3 1
1 3 5
这样的话用prim得出的结论是5+7=12,而实际上,我们可以先到2号点,再从二号到3号。这样答案就是最优解7+1=8;故若采用最小生成树方法时,便应当考虑kruskal算法。
思路是这样的:
先用bfs()遍历完所有可能遍历到的节点,标记能遍历到的,然后对原式进行排序先从去的高处向下排,再按路径长度按从小到大排序,然后就套用Kruskal模板。
为什么要用bfs()先遍历呢?这是因为或许会出现一种情况:一条边的两端不可以被遍历到,但是这条边很短,且终点很高,容易被Kruskal添加进去,故要避免这种情况。
先用bfs()遍历,能被遍历的节点被标记为need=true;添加边时应当使两端顶点need都为true;
#include<list>#include<queue>#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>#include<vector>using namespace std;struct place//景点结点{ int from; int to; int disten;};struct rec//辅助bfs(){ int to; int weight; rec* next;};rec* vec[100001];const int inf = 0x3f3f3f3f;bool need[100001];bool used[100001];int hei[100001];place p[2000001];int parent[100001];int n, m;int coun;//统计遍历的边数 [0,coun)int reach;void addedge(int f,int t,int w){ p[coun++]=place{f,t,w}; rec *l=new rec; l->to=t; l->weight=w; l->next=vec[f]; vec[f]=l;}bool com(place a, place b){ if (hei[a.to] == hei[b.to]) return a.disten < b.disten; else return hei[a.to]>hei[b.to];}void bfs() //遍历所有可能到达的结点{ queue<int>q; q.push(1); need[1]=true; while(!q.empty()) { int t=q.front(); q.pop(); if(++reach==n) return ; for( rec* it=vec[t]; it; it=it->next) { if(need[it->to]==false) { need[it->to]=true; q.push(it->to); } } }}int getpare(int a)//parent【a】=getparent(parent【a】),这句话会很好的提高效率,加快访问到根节点的时间{ return (parent[a] == a) ? a : parent[a]=getpare(parent[a]);}void kruskal()//最小生成树{ long long dis = 0; sort(p, p + coun, com);//排序的原则是去的最高点优先,然后是路径长度 for (int q = 1; q <= n; ++q) parent[q] = q; for (int i = 0; i<coun; ++i) { if (need[p[i].from]&&need[p[i].to]) { int p1 = getpare(p[i].from); int p2 = getpare(p[i].to); if (p1 != p2) { dis += p[i].disten; parent[getpare(p[i].from)]=getpare(p[i].to); } } } printf("%lld\n",dis);}int main(){ scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) scanf("%d", &hei[i]); reach = 0; coun = 0; int f, t, w; for (int i = 1; i <= m; ++i) { scanf("%d%d%d", &f, &t, &w); if (hei[f] >= hei[t]) { addedge(f,t,w); } if(hei[f]<=hei[t]) { addedge(t,f,w); } } bfs(); printf("%d ",reach); kruskal();}
0 0
- 滑雪与时间胶囊
- 【SCOI2012】滑雪与时间胶囊
- bzoj2753滑雪与时间胶囊
- [SCOI2012]滑雪与时间胶囊
- 【BZOJ2753 || SCOI2012】滑雪与时间胶囊
- 【SCOI2012】【kruscal变形】滑雪与时间胶囊
- [BZOJ 2753][SCOI2012]滑雪与时间胶囊
- bzoj2753: [SCOI2012]滑雪与时间胶囊 MST
- bzoj 2753 [SCOI2012]滑雪与时间胶囊
- 【SCOI2012】【BZOJ2753】滑雪与时间胶囊
- CODEVS 2399 滑雪与时间胶囊
- 2753: [SCOI2012]滑雪与时间胶囊
- BZOJ 2753 [SCOI2012] 滑雪与时间胶囊
- BZOJ2753: [SCOI2012]滑雪与时间胶囊
- 2753: [SCOI2012]滑雪与时间胶囊
- bzoj2753 [SCOI2012]滑雪与时间胶囊
- BZOJ2753: [SCOI2012]滑雪与时间胶囊
- SCOI2012(HYSBZ2753)“滑雪与时间胶囊”
- 模仿通讯录侧滑栏
- 异常处理机制
- SQL 创建存储过程PROCEDURE
- logback logback.xml常用配置详解(二)<appender>
- <读书笔记>软件调试之道 :问题的核心-如何修复缺陷
- 滑雪与时间胶囊
- Android - LayoutInflater和inflate方法的用法
- logback logback.xml常用配置详解(三) <filter>
- 分段和分页 存储管理
- 下拉菜单
- Qt4下创建自定义窗体
- 表达式包含的隐式类型转换
- Python学习 (七 错误、调试和测试)
- struts2的中文乱码处理,struts出现中文乱码怎么处理.如何解决struts的中文乱码问题?