题目链接:https://vjudge.net/problem/HYSBZ-1415
1415: [Noi2005]聪聪和可可
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2101 Solved: 1228
[Submit][Status][Discuss]
Description
Input
数据的第1行为两个整数N和E,以空格分隔,分别表示森林中的景点数和连接相邻景点的路的条数。 第2行包含两个整数C和M,以空格分隔,分别表示初始时聪聪和可可所在的景点的编号。 接下来E行,每行两个整数,第i+2行的两个整数Ai和Bi表示景点Ai和景点Bi之间有一条路。 所有的路都是无向的,即:如果能从A走到B,就可以从B走到A。 输入保证任何两个景点之间不会有多于一条路直接相连,且聪聪和可可之间必有路直接或间接的相连。
Output
输出1个实数,四舍五入保留三位小数,表示平均多少个时间单位后聪聪会把可可吃掉。
Sample Input
【输入样例1】
4 3
1 4
1 2
2 3
3 4
【输入样例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9
4 3
1 4
1 2
2 3
3 4
【输入样例2】
9 9
9 3
1 2
2 3
3 4
4 5
3 6
4 6
4 7
7 8
8 9
Sample Output
【输出样例1】
1.500
【输出样例2】
2.167
1.500
【输出样例2】
2.167
HINT
【样例说明1】
开始时,聪聪和可可分别在景点1和景点4。
第一个时刻,聪聪先走,她向更靠近可可(景点4)的景点走动,走到景点2,然后走到景点3;假定忽略走路所花时间。
可可后走,有两种可能:
第一种是走到景点3,这样聪聪和可可到达同一个景点,可可被吃掉,步数为1,概率为 。
第二种是停在景点4,不被吃掉。概率为 。
到第二个时刻,聪聪向更靠近可可(景点4)的景点走动,只需要走一步即和可可在同一景点。因此这种情况下聪聪会在两步吃掉可可。
所以平均的步数是1* +2* =1.5步。
对于所有的数据,1≤N,E≤1000。
对于50%的数据,1≤N≤50。
题意(论文上的题):
题解:
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const double EPS = 1e-6; 15 const int INF = 2e9; 16 const LL LNF = 9e18; 17 const int MOD = 1e5; 18 const int MAXN = 1e3+10; 19 20 vector<int>g[MAXN]; //用矩阵保存图信息的话速度非常慢,所以用vector 21 int vis[MAXN][MAXN]; 22 int next[MAXN][MAXN]; 23 double dp[MAXN][MAXN]; 24 int n, m, C, M; 25 26 queue<int>Q; 27 void bfs(int st) 28 { 29 while(!Q.empty()) Q.pop(); 30 next[st][st] = st; 31 int sz = g[st].size(); 32 for(int i = 0; i<sz; i++) 33 { 34 int v = g[st][i]; 35 next[st][v] = v; 36 Q.push(v); 37 } 38 while(!Q.empty()) 39 { 40 int u = Q.front(); 41 Q.pop(); 42 sz = g[u].size(); 43 for(int i = 0; i<sz; i++) 44 { 45 int v = g[u][i]; 46 if(next[st][v]!=-1) continue; 47 next[st][v] = next[st][u]; 48 Q.push(v); 49 } 50 } 51 } 52 53 double dfs(int st, int en) 54 { 55 if(st==en) return 0; // 如果某个时刻在同一位置,则聪聪把可可吃点,不花时间 56 if(next[st][en]==en || next[next[st][en]][en]==en) return 1; //因为聪聪先走,所以如果在两步之内到达可可的位置,则把它吃掉,花了一个单位时间 57 if(vis[st][en]) return dp[st][en]; 58 vis[st][en] = true; 59 60 int cnt = 0, sz = g[en].size(); 61 double sum = dfs(next[next[st][en]][en], en)+1; 62 for(int i = 0; i<sz; i++) 63 { 64 int v = g[en][i]; 65 cnt++; 66 sum += dfs(next[next[st][en]][en], v)+1; 67 } 68 return dp[st][en] = sum/(cnt+1); 69 } 70 71 int main() 72 { 73 while(scanf("%d%d", &n,&m)!=EOF) 74 { 75 scanf("%d%d", &C, &M); 76 for(int i = 1; i<=n; i++) 77 g[i].clear(); 78 while(m--) 79 { 80 int u, v; 81 scanf("%d%d", &u,&v); 82 g[u].push_back(v); 83 g[v].push_back(u); 84 } 85 for(int i = 1; i<=n; i++) //根据编号大小对相邻点进行排序,以便在路径长度相同时选编号最小的。 86 sort(g[i].begin(), g[i].end()); 87 88 memset(next, -1, sizeof(next)); 89 for(int i = 1; i<=n; i++) 90 bfs(i); 91 memset(vis, false, sizeof(vis)); 92 double step = dfs(C, M); 93 printf("%.3lf ", step); 94 } 95 }