USACO Sweet Butter 与图的寻径算法
来源:互联网 发布:数据恢复技术 pdf 编辑:程序博客网 时间:2024/05/17 08:43
此题的实际模型如下:给定一个有P个顶点的无向含权图,选择一个顶点,使得从该点到给定的N个顶点的权值之和最小。
最经典的就是Dijkstra算法了。这个经典的不能再经典的贪心策略,应该都知道的吧。每次都需要在Distance数组中寻求一个最小值,如果图很大,则在此处花费的时间会很多,而堆则可以在O(1)的时间内求得最小值,并且维护一个堆所需的时间都是在log级的。因此考虑把Distance数组的值用堆来存储。
用堆操作的Dijkstra的思想还是与一般的思想类似:
初始化Distance[]=MAX,然后将源点t放入堆中(这就与Distance[t]=0类似),再从堆中找出一个最小值没有被确定的点minp(就是Distance[minp]=MAX),将其确定下来,Distance[minp]=mins,mins为从堆中取出来的那个最小值,接着由这个最小值所连接的点求出从源点到这些点的路径长,若所连接的点没有求出最小值,Distance[i]=MAX,则将这个点放入堆中,这就好比用for循环去修改每一个Distance[]的值,不同的地方在于堆中存放的是源点到各个顶点的最小值,如果刚求出来的顶点在Distance[]中已经被赋值了,说明求出来的肯定不是最小值,就像普通Dijkstra的Mark[]一样,mark过的点是不能再被计算的,所以不能放Distance[]中有值的点。这样Dijkstra的部分就完成了。
Dijkstra算法真的是简洁优雅的典范,也可以看出,大学里的《数据结构》这么课学好了,走出学校后确实是很厉害的,寻径算法在现实中出现频率还是很高的。
另外一种方法是改进的BFS算法:
可以理解为动态规划,不过也不是严格的动态规划。你可以写出下面的递推式:
Distance(start, now) = Min(Distance(start, k) + Distance(k, now), for k in start's adjacnet list)
但如果这个式子是有问题的,请见下面的广搜加深搜的说明。但有问题可以想办法解决,一种办法是:对于枚举的每个牧场 i,令Distance[j]表示 i 到 j 的距离,初始值为INT_MAX,其中Distance[i]=0。维护一个队列,初始为q[1]=i,由队首枚举其他的牧场 j 更新牧场 i 到 j 的最短距离并同时拓展队列。直到队列空为止。这样就求出了点i到所有点的最短距离。和BFS差不多吧,但不同的是宽度优先搜索中一个点出了队列就不可能重新进入队列,这个算法中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本身被改进,于是再次用来改进其它的点,这样反复迭代下去。
其实也可以广搜加上深搜:
基本思路还是和上面说的BFS一致,主要还是因为一个点被修改后,位于它上层的点也可能受到影响,它上层的上层的点也可能收到影响,这个就是DFS的回溯的。
- /*
- ID:fairyroad
- LANG:C++
- TASK:butter
- */
- #include<fstream>
- #include<cstring>
- #include<queue>
- #include <limits>
- using namespace std;
- ifstream fin("butter.pushed");
- ofstream fout("butter.out");
- const int MAX = 805;
- struct vertex
- {
- int end,len;
- };
- vertex adj[MAX][MAX];
- int cnt[MAX]={0}, cowpos[505]={0}, n, p, c;
- bool pushed[MAX]={0};
- int distance[MAX];
- int search(int start)
- {
- memset(pushed, 0, sizeof(pushed));
- for(int k = 1; k <= p; k++)
- distance[k] = numeric_limits<int>::max();
- queue<int> Q;
- Q.push(start);
- pushed[start] = true;
- distance[start] = 0;
- while(!Q.empty())
- {
- int x = Q.front();
- Q.pop();
- pushed[x] = false;
- for(int j = 0; j < cnt[x]; j++)
- {
- if(distance[x]+adj[x][j].len < distance[adj[x][j].end])
- {
- distance[adj[x][j].end] = distance[x]+adj[x][j].len;
- if(!pushed[adj[x][j].end])
- {
- Q.push(adj[x][j].end);
- pushed[adj[x][j].end] = true;
- }
- }
- }
- }
- int ans = 0;
- for(int i = 1; i<=n; i++)
- {
- if(distance[cowpos[i]]==numeric_limits<int>::max()) return -1;
- else ans+=distance[cowpos[i]];
- }
- return ans;
- }
- int main()
- {
- memset(cnt, 0, sizeof(cnt));
- fin>>n>>p>>c;
- for(int i = 1; i<=n; i++)
- fin>>cowpos[i];
- for(int i = 1, s, t, value; i <= c; i++)
- {
- fin>>s>>t>>value;
- adj[s][cnt[s]].end = t; adj[s][cnt[s]].len = value; cnt[s]++;
- adj[t][cnt[t]].end = s; adj[t][cnt[t]].len = value; cnt[t]++;
- }
- int res, min = numeric_limits<int>::max();
- for(int i = 1; i <= p; i++)
- {
- res = search(i);
- if(res < min && res != -1) min = res;
- }
- fout<<min<<endl;
- return 0;
- }
- USACO Sweet Butter 与图的寻径算法
- USACO--3.2Sweet Butter+推优化的Dijkstral算法
- USACO 3.2 Sweet Butter (butter)
- USACO: chap3 Sweet Butter
- usaco Sweet Butter
- [usaco] Sweet Butter
- USACO 3.2 Sweet Butter
- USACO - 3.2.6 Sweet Butter 香甜的黄油 Dijkstra(迪杰斯特拉算法)+枚举
- USACO Sweet Butter, 难题,Bellman-Ford算法 + SPFA优化
- USACO 3.2.6 sweet butter
- USACO Sweet Butter 解题报告
- [Usaco-3.2.6] Sweet Butter香甜的黄油
- 【USACO题库】3.2.6 Sweet Butter香甜的黄油
- USACO 3.2 Sweet Butter 香甜的黄油 (Bellman DIJ SPFA)
- JZOJ1287.【USACO题库】3.2.6 Sweet Butter香甜的黄油
- 【USACO题库】3.2.6 Sweet Butter香甜的黄油
- usaco Chapter 3 section 3.2 Sweet Butter
- [usaco]单源最短路径:3.3.5 Sweet Butter
- 工作笔录3
- 学习笔记一:使用Mutex实现线程之间互斥
- Adding And Removing Remote Branches
- 学习如何做一个论坛(1)转百度知道
- 我开发的stm32以太网开发工具(深蓝DevBoard)
- USACO Sweet Butter 与图的寻径算法
- php递归函数实现遍历指定文件下的目录与文件数量
- 第四章:良好的坏习惯
- 北京这些天
- 第五章:另一条路
- 利用动态代理实现AOP的简单示例(JDK和cglib分别实现)
- 对象放入ArrayList时出错
- 一个下载资源的好地方
- 字符串题目推荐及解题报告