PAT天梯赛练习题——L3-008. 喊山(邻接表+BFS)
2016-06-24 23:49
477 查看
L3-008. 喊山
时间限制
150 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)
一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。
输入格式:
输入第一行给出3个正整数n、m和k,其中n(<=10000)是总的山头数(于是假设每个山头从1到n编号)。接下来的m行,每行给出2个不超过n的正整数,数字间用空格分开,分别代表可以听到彼此的两个山头的编号。这里保证每一对山头只被输入一次,不会有重复的关系输入。最后一行给出k(<=10)个不超过n的正整数,数字间用空格分开,代表需要查询的山头的编号。
输出格式:
依次对于输入中的每个被查询的山头,在一行中输出其发出的呼喊能够连锁传达到的最远的那个山头。注意:被输出的首先必须是被查询的个山头能连锁传到的。若这样的山头不只一个,则输出编号最小的那个。若此山头的呼喊无法传到任何其他山头,则输出0。
输入样例:
7 5 4
1 2
2 3
3 1
4 5
5 6
1 4 5 7
输出样例:
2
6
4
0
这题第一组数据可能不是很好理解,我一开始以为是3,但是后来发现1与3之间也有一条边,因此1-2-3这条路径默认作废。即若A-B有多条路径,那么只算其中一条最短的。
然后就是BFS这里面如何知道我当前BFS到第几层呢,一开始我想比如1这个节点有2 3 4,然后2 3 4都往队列里压,是当E[NOW].size()不等于0的时候意味这这个点可以继续向外拓展,然后当前层数++,交上去中间两组是错的。调试发现显然是错的,1-2、3、4,其实只有一层,但是实际上算了3层,因此原来的想法计算出来的是可拓展的次数而非层数。那如何去记录当前的层数呢?用一个pair(结构体也可)来把两个数据结合起来——当前点now和now所在层数d,每一次压入队列的时候把v的层数带上,这样就可以根据当前点来知道当前的层数。由于m题目没说就不用前向星了省的段错误
代码:
时间限制
150 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
陈越
喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤。呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的。原来它是彝族先民用来求援呼救的“讯号”,慢慢地人们在生活实践中发现了它的实用价值,便把它作为一种交流工具世代传袭使用。(图文摘自:http://news.xrxxw.com/newsshow-8018.html)
一个山头呼喊的声音可以被临近的山头同时听到。题目假设每个山头最多有两个能听到它的临近山头。给定任意一个发出原始信号的山头,本题请你找出这个信号最远能传达到的地方。
输入格式:
输入第一行给出3个正整数n、m和k,其中n(<=10000)是总的山头数(于是假设每个山头从1到n编号)。接下来的m行,每行给出2个不超过n的正整数,数字间用空格分开,分别代表可以听到彼此的两个山头的编号。这里保证每一对山头只被输入一次,不会有重复的关系输入。最后一行给出k(<=10)个不超过n的正整数,数字间用空格分开,代表需要查询的山头的编号。
输出格式:
依次对于输入中的每个被查询的山头,在一行中输出其发出的呼喊能够连锁传达到的最远的那个山头。注意:被输出的首先必须是被查询的个山头能连锁传到的。若这样的山头不只一个,则输出编号最小的那个。若此山头的呼喊无法传到任何其他山头,则输出0。
输入样例:
7 5 4
1 2
2 3
3 1
4 5
5 6
1 4 5 7
输出样例:
2
6
4
0
这题第一组数据可能不是很好理解,我一开始以为是3,但是后来发现1与3之间也有一条边,因此1-2-3这条路径默认作废。即若A-B有多条路径,那么只算其中一条最短的。
然后就是BFS这里面如何知道我当前BFS到第几层呢,一开始我想比如1这个节点有2 3 4,然后2 3 4都往队列里压,是当E[NOW].size()不等于0的时候意味这这个点可以继续向外拓展,然后当前层数++,交上去中间两组是错的。调试发现显然是错的,1-2、3、4,其实只有一层,但是实际上算了3层,因此原来的想法计算出来的是可拓展的次数而非层数。那如何去记录当前的层数呢?用一个pair(结构体也可)来把两个数据结合起来——当前点now和now所在层数d,每一次压入队列的时候把v的层数带上,这样就可以根据当前点来知道当前的层数。由于m题目没说就不用前向星了省的段错误
代码:
#include<iostream> #include<algorithm> #include<cstdlib> #include<sstream> #include<cstring> #include<cstdio> #include<string> #include<deque> #include<stack> #include<cmath> #include<queue> #include<set> #include<map> using namespace std; #define INF 0x3f3f3f3f #define MM(x) memset(x,0,sizeof(x)) #define MMINF(x) memset(x,INF,sizeof(x)) typedef long long LL; const double PI=acos(-1.0); const int N=10010; typedef pair<int,int> pii; vector<int>E ; int vis ; void init() { for (int i=0; i<N; i++) E[i].clear(); } int bfs(int s) { MM(vis); queue<pii>Q; Q.push(pii(s,0)); vis[s]=1; int d=0,p=s; while (!Q.empty()) { pii now=Q.front(); Q.pop(); if(now.second>d)//层数大于d,更新信息 { p=now.first; d=now.second; } else if(now.second==d&&now.first<p)//层数相等但点更小,也更新 p=now.first; int SZ=E[now.first].size(); for (int i=0; i<SZ; i++) { int v=E[now.first][i]; if(!vis[v]) { Q.push(pii(v,now.second+1)); vis[v]=1;//标记访问过 } } } if(p==s) return 0; else return p; } int main(void) { int m,n,k,i,j,a,b,c; while (~scanf("%d%d%d",&n,&m,&k)) { init(); for (i=0; i<m; i++) { scanf("%d%d",&a,&b); E[a].push_back(b); E[b].push_back(a); } for (i=0; i<k; i++) { scanf("%d",&c); printf("%d\n",bfs(c)); } } return 0; }
相关文章推荐
- Surrounded Regions
- Word Ladder, Gray Code
- UVA 11624
- HDU1495
- HDU2612 Find a way
- HDU1241 Oil Deposits
- Hdu2444二分图
- 最少步数BFS
- 转v_JULY_v的 BFS和DFS优先搜索算法
- 2015 寒假搜索专题 I - Meteor Shower(BFS)
- Same Tree
- E - Roads in the North
- DFS&BFS算法总结(1)
- Word Ladder I
- 图的BFS和DFS学习笔记
- [LeetCode] Binary Tree Level Order Traversal
- [LeetCode] Binary Tree Level Order Traversal II
- POJ 3278 Catch That Cow (bfs)(两种方式)
- POJ 2251 Dungeon Master(三维bfs)
- 关于BFS搜索的思想, 最简单的水题,不过深有体会啊。