zoj2913 Bus Pass ——BFS入门题

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1912

题目大意:

  有很多个地区,有几条公交线经过一些地区,求出一个地区,满足,使这个地区到这些公交线上的所有公交站的距离中的最大值,最小。(这里的距离指的是两点之间的边数)

思路:

  对于这些公交站中的每一个点,BFS,求出出当前点外,其他所有点到这个点的最小距离,然后对于公交站上的其他点,也进行同样地操作,不断更新所有点到公交站上的当前点的最小距离的较大值,然后遍历所有点,求出距离最小的一个点。用res1数组存储。res数组的作用是对于公交线上的每个点,BFS其他点的时候,临时存放其他点到这个公交站的最小距离,然后在与res1数组进行比较,用来更新res1数组。

注意:

  visited数组,标记这个是不是被访问过,并且标记的顺序要想清楚!把这个点入队的时候就要标记它被访问了,而不是它出队的时候再标记!这是因为,如果两天点同时和一个点相邻,如果等点出队的时候在标记的话,就会产生这个点被访问两次的情况,这个问题让我纠结了一个星期……我去……

比如这种情况,C和A,B同时相邻,假如:先访问A,res[B] = res[C] = 2,把A标记,然后出队;再访问B,res[C] = 3,C的值显然是不对的,所以,当把B,C两个点入队的时候,就把他们标记为已经访问,就可以了……

  做这个题目感触挺大的,首先,写代码要全神贯注,不能有一点儿疏忽,否则很容易犯那种超级难找出来的隐蔽的错误,一定要考虑明白再写;然后就是数组的下标什么的,养成好习惯,到底什么时候该从0开始,什么时候该从1开始,我觉得从1开始比较保险,因为有的时候会用到编号,比如这道题目,点的标号从1开始;最后就是思考这种题目应该如何存储题目给的信息,这个东西是看的书上的思想;

  自己写代码比看着人家的代码写感觉和收获是完全不一样的。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cctype>
 6 #include <stack>
 7 #include <queue>
 8 #include <cmath>
 9 #include <algorithm>
10 #define lson l, m, rt<<1
11 #define rson m+1, r, rt<<1|1
12 using namespace std;
13 typedef long long int LL;
14 const int MAXN =  0x3f3f3f3f;
15 const int  MIN =  -0x3f3f3f3f;
16 const double eps = 1e-9;
17 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1},
18   {1,1},{1,-1},{-1,-1}};
19 const int MAX = 10000+10;
20 int edge[MAX][11], res[MAX], res1[MAX], ve, pa, mz[MAX];
21 bool visited[MAX];
22 queue<int> qt;
23 void bfs(int id){
24   res[id] = 1; qt.push(id); int te;
25   visited[id] = true;
26   while (!qt.empty()){
27     te = qt.front();  qt.pop();
28     for (int k = 1; k <= mz[te]; ++k){
29       if (!visited[edge[te][k]]){
30         qt.push(edge[te][k]);
31         res[edge[te][k]] = max(res[edge[te][k]], res[te] + 1);
32         visited[edge[te][k]] = true;
33       }
34     }
35   }
36   for (int k = 1; k <= MAX; ++k) {
37     res1[k] = max(res1[k], res[k]);
38   }
39 }
40 int main(void){
41 #ifndef ONLINE_JUDGE
42   freopen("zoj2913.in", "r", stdin);
43 #endif
44   int t;scanf("%d", &t);
45   while (t--){
46     scanf("%d%d", &ve, &pa); int n;
47     memset(mz, 0, sizeof(mz));
48     for (int i = 1; i <= ve; ++i){
49       scanf("%d", &n); scanf("%d", &mz[n]);
50       for (int j = 1; j <= mz[n]; ++j){
51         scanf("%d", &edge[n][j]);
52       }
53     }
54     int id;
55     for (int i = 1; i <= MAX; ++i) res1[i] = -1;
56     for (int i = 1; i <= pa; ++i){
57       scanf("%d", &n);
58       for (int j = 1; j <= n; ++j){
59         scanf("%d", &id);
60         memset(visited, false, sizeof(visited));
61         for (int k = 1; k <= MAX; ++k) res[k] = -1;
62         bfs(id);
63         for (int k = 1; k <= MAX; ++k)
64           res1[k] = max(res1[k], res[k]);
65       }
66     }
67     int fu = MAX, fid;
68     for (int i = 1; i <= MAX; ++i){
69       if (res1[i] != -1 && fu > res1[i]){
70         fu = res1[i]; fid = i;
71       }
72     }
73     printf("%d %d\n", fu, fid);
74   }
75 
76   return 0;
77 }

  不管怎么样,过程如何纠结,想了多少时间,写了多少遍,最后还是1A了……

posted on 2013-04-13 01:29  aries__liu  阅读(575)  评论(0编辑  收藏  举报