题目链接: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了……