cf813C(bfs)

题目链接:http://codeforces.com/problemset/problem/813/C

题意:给出一颗树,开始时两个人 Alice 和 Bob 分别站在 1(树根)和 x 处.此后每一次操作两人都可以选择在原地不动或者移动到相邻的节点(Bob先移动);

直至两人移到同一个位置,两人移动的总步数为 ans,Alice要使 ans 尽量小,Bob 要使 ans 尽量大,输出ans;

思路:假设最终在 p 位置相遇,显然 p 是由先移动的 Bob 决定的,即 p 能使 ans 最大;

用 dis1[p] 表示 1 到 p 的距离,dis2[p] 表示 x 到 p 的距离,要满足 Alice 和 Bob 在移动到 p 之前不相遇,所以有 dis1[p] > dis2[p],那么显然有 ans = 2 * dis1[p];

即:先 bfs 出 1 和 x 到其他节点的最短距离,再遍历所有节点,对于节点 i,若满足 dis1[i] > dis2[i] ,则 ans = max(ans, 2 * dis1[i]),最终输出 ans 即可;

代码:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <vector>
 4 #include <queue>
 5 #include <string.h>
 6 using namespace std;
 7 
 8 const int MAXN = 2e5 + 10;
 9 vector<int> mp[MAXN];
10 bool vis[MAXN];
11 
12 
13 void bfs(int dis[MAXN], int p){//求以 p 为根时其余个点到 p 的距离
14     memset(vis, 0, sizeof(vis));
15     int ans = 0, cnt1 = 1, cnt2 = 0;
16     queue<int> q;
17     q.push(p);
18     vis[p] = true;
19     while(!q.empty()){
20         while(cnt1--){
21             int cnt = q.front();
22             q.pop();
23             for(int i = 0; i < mp[cnt].size(); i++){
24                 int cc = mp[cnt][i];
25                 if(!vis[cc]){
26                     q.push(mp[cnt][i]);
27                     vis[mp[cnt][i]] = true;
28                     cnt2++;
29                 }
30             }
31             dis[cnt] = ans;
32         }
33         cnt1 = cnt2;
34         cnt2 = 0;
35         ans++;
36     }
37 }
38 
39 int main(void){
40     int n, x;
41     scanf("%d%d", &n, &x);
42     for(int i = 0; i < n - 1; i++){
43         int s, e;
44         scanf("%d%d", &s, &e);
45         mp[s].push_back(e);
46         mp[e].push_back(s);
47     }
48     int dis1[MAXN], dis2[MAXN];
49     bfs(dis1, 1);
50     bfs(dis2, x);
51     int ans = 0;
52     for(int i = 1; i <= n; i++){
53         if(dis1[i] > dis2[i] && mp[i].size() == 1){
54             ans = max(ans, dis1[i]*2);
55         }
56     }
57     cout << ans << endl;
58     return 0;
59 }
View Code
原文地址:https://www.cnblogs.com/geloutingyu/p/6951975.html