HDU 2377 最短路
来源:互联网 发布:搜游网络 融资 编辑:程序博客网 时间:2024/06/06 12:46
/*
最短路, 终点集合到s的最远距离最短,求s. 即已知终点集{d}求一s使得Min{ max{ dis(s, di) } }
好题
思路: 多次单源最短路,选出最大值
在对每个x进行分层搜索的过程中, 用max_d[y]记录每个地区x到达地区y的最短距离中的最大值. 最后求得的Star Value就是max_d[]中的最小值.
由于题目的特殊性`边权都为1`,所以可以借助这一性质变换一下SPFA使其更快。
说个题外话,在临高时看到有个学弟拓扑排序用到“分层思想”,一直觉得很妙。就是拓扑后我们可以得到floor[i],如果floor[i] > floor[j],即说明j是i的前驱节点(层数越小越接近root); 而floor[i] == floor[j]的话则i,j的相对顺序无所谓,因为他们都在“同一层”。
这里因为边权都为1,所以SPFA可以用到上述的分层思想,层数越高,离source越远。代码里面floors就表示层数,Q是滚动队列,就是一层一层地relax后继节点。
注意!!千万不要以为max_d[]是最短路算法里面的dis[],这里的max_d[i]是到点i到终点集合{di}的最大值!而常规最短路算法里的dis[]已经被省略为“层数”了,不需要记录,所以没开数组。
最重要的是学到一个tip!!以前我做多次最短路的时候总要每次都初始化visit[] -> false,但其实不用的,我们只要用一个变量when表示“这是第几次做SPFA(或其他)“,然后每次入队前都看”是否当前visit[v] == when就可以直到改点是否已经入过队......
*/
#include <stdio.h>#include <string.h>#include <vector>#include <deque>using namespace std;#define debug printf("!\n")#define INF 999999999#define MAXN 10000int n;int max_d[MAXN];int visit[MAXN];vector<int> v[MAXN];void SPFA(int s, int when);void init();int main(){ int cases, query, id, m, y, x; scanf("%d", &cases); while(cases--) { scanf("%d%d", &n, &query); init(); for(int i = 0; i < n; i++) { scanf("%d%d", &id, &m); while(m--) { scanf("%d", &y); v[id].push_back(y); } } int when = 0; while(query--) { scanf("%d", &m); while(m--) { scanf("%d", &x); SPFA(x, ++when); } } int ans = INF, ans_id = -1; for(int i = 1; i < MAXN; i++) if(!v[i].empty() && max_d[i] < ans) ans = max_d[i], ans_id = i; printf("%d %d\n", ans, ans_id); } return 0;}void init(){ for(int i = 0; i < MAXN; i++) v[i].clear(); memset(max_d, 0, sizeof(max_d)); memset(visit, 0, sizeof(visit));}void SPFA(int s, int when){ deque<int> Q[2]; int cur = 0; Q[cur].push_back(s); max_d[s] = max(max_d[s], 1); visit[s] = when; int floors = 1; do { floors++; while(!Q[cur].empty()) { int at = Q[cur].front(); Q[cur].pop_front(); for(int Size = v[at].size(), i = 0; i < Size; i++) { int to = v[at][i]; if(visit[to] != when) { //是否已入队 //max_d[to] = max(max_d[to], max_d[at]+1); 这句是不对的,因为这个分层跟拓扑排序的分层是不一样的,拓扑排序是要在入度为0时才能加进队Q,所以可以这样写,但是这里只要第一次遇见点to就必须得入队,因为要的是最短路径 max_d[to] = max(max_d[to], floors); //不把这句放在if外面,因为这里的max_d[to]是距离s的最短路径,最短路径也就是最小层数,最小层数在to第一次入队的时候已经得到了 visit[to] = when; Q[1-cur].push_back(to); } } } cur = 1 - cur; } while(!Q[cur].empty());}
- HDU 2377 最短路
- HDU 2377 Bus Pass 最短路SPaf
- hdu 2377 Bus Pass(最短路spfa)
- HDU 2377 Bus Pass 最短路
- HDU 2377 Bus Pass(最短路 SPFA)
- 最短路 2544hdu
- HDU 2544 最短路
- hdu 1245 最短路
- HDU最短路总结
- hDU 最短路
- hdu 1874 (最短路)
- hdu 2112 (最短路)
- HDU-2544 最短路
- Hdu-2544 最短路
- hdu 2066 最短路
- HDU 2544 最短路
- 最短路 hdu
- hdu 2544 最短路
- 执行xcopy命令后出现Invalid num of parameters错误的解决办法
- Linux 服务配置之 FTP 服务
- [实验]在同一个 canvas 元素中绘制不同颜色的图形
- 计算机常用算法
- SharePoint的安装和配置-PowerShell
- HDU 2377 最短路
- Python3.3 print函数用法,print 格式化输出
- HDU 2586 LCA
- Class.asSubclass浅谈
- Log4j详解
- 高级Bash脚本编程指南(25):文本处理命令(一)
- 算法导论-第13章
- C#小点点(通过一段代码,想开去)
- [Java小程序] 实现简单计算器