题干:
The Berland road network consists of n cities and of m bidirectional roads. The cities are numbered from 1 to n, where the main capital city has number n, and the culture capital — number 1. The road network is set up so that it is possible to reach any city from any other one by the roads. Moving on each road in any direction takes the same time.
All residents of Berland are very lazy people, and so when they want to get from city v to city u, they always choose one of the shortest paths (no matter which one).
The Berland government wants to make this country's road network safer. For that, it is going to put a police station in one city. The police station has a rather strange property: when a citizen of Berland is driving along the road with a police station at one end of it, the citizen drives more carefully, so all such roads are considered safe. The roads, both ends of which differ from the city with the police station, are dangerous.
Now the government wonders where to put the police station so that the average number of safe roads for all the shortest paths from the cultural capital to the main capital would take the maximum value.
Input
The first input line contains two integers n and m (2 ≤ n ≤ 100, ) — the number of cities and the number of roads in Berland, correspondingly. Next mlines contain pairs of integers vi, ui (1 ≤ vi, ui ≤ n, vi ≠ ui) — the numbers of cities that are connected by the i-th road. The numbers on a line are separated by a space.
It is guaranteed that each pair of cities is connected with no more than one road and that it is possible to get from any city to any other one along Berland roads.
Output
Print the maximum possible value of the average number of safe roads among all shortest paths from the culture capital to the main one. The answer will be considered valid if its absolute or relative inaccuracy does not exceed 10 - 6.
Examples
Input
4 4
1 2
2 4
1 3
3 4
Output
1.000000000000
Input
11 14
1 2
1 3
2 4
3 4
4 5
4 6
5 11
6 11
1 8
8 9
9 7
11 7
1 10
10 4
Output
1.714285714286
Note
In the first sample you can put a police station in one of the capitals, then each path will have exactly one safe road. If we place the station not in the capital, then the average number of safe roads will also make .
In the second sample we can obtain the maximum sought value if we put the station in city 4, then 6 paths will have 2 safe roads each, and one path will have 0 safe roads, so the answer will equal .
题目大意:
有n个城市,编号为1-n,有m条双向路,现要在一个点设立警察局,通过这个点的路就是安全路,求1到n的每条最短路上平均的安全路的条数,即安全路总可能条数/总最短路条数。
题意:
给你n个点(编号为1到n),m条边的有向图(无环,无重边,每个点都与其他点连通),现在要在一个点上建一个警察局,一条边,只要有一端与警察局相连,它就是安全的边,否则它就是不安全的边,现在问在哪个点建警察局能使从1到n的每条最短路上平均的安全路的条数,即最大。这里的每条最短路的定义是最短路上有1条边不一样就是不一样的最短路径。
思路:
根据这题不同最短路的定义,我们可以知道对于中间2~n-1的节点来说,如果放置警察局,那么它(设为i)所能产生安全的道路条数为从i到1和i到n的最短路径条数相乘,结果是从1到n且经过i的最短路径条数,且对于每条不同的最短路径来说会产生2条安全边。所以我们枚举i来跑遍SPFA就可以了。
思路:
题目比较难理解,吃了英语的亏,首先是安全路总可能条数,在点2-n-1中某个点x建警察局,则在每条最短路中会产生2条安全路,在x点建立警察局所产生的总条数就是1到x的路径*x到n的路径;总最短路条数便是1到n的所有最短路条数,于是可以用spfa计算最短路,dp记录条数。另外要注意最短路和条数要使用long long,否则会载在Test 22,因为假设六个一组形成16个4叉路,剩下四个再形成三叉路,则总最短路条数为2^32*3,大于int范围。(思路比较难理解,建议边看代码边理解)。
解题报告:
AC代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX = 200 + 5;
vector<int> vv[MAX];
ll dis[MAX];
ll ans[MAX];
bool vis[MAX];
int n,m;
struct Point {int pos;ll c;Point(){}Point(int pos,ll c):pos(pos),c(c){}bool operator < (const Point & b)const{return c > b.c;}
};
void Dijkstra(int st) {for(int i = 1; i<=n; i++) dis[i] = 100000000000;memset(ans,0,sizeof ans);memset(vis,0,sizeof vis);dis[st]=0;ans[st]=1;priority_queue<Point> pq;pq.push(Point(st,0));while(!pq.empty()) {Point cur = pq.top();pq.pop();if(vis[cur.pos]) continue;vis[cur.pos] = 1;int size = vv[cur.pos].size();for(int i = 0; i<size; i++) {int v = vv[cur.pos][i];if(vis[v]) continue;if(dis[v] == dis[cur.pos] + 1) {ans[v] += ans[cur.pos];}else if(dis[v] > dis[cur.pos] + 1) {ans[v] = ans[cur.pos];dis[v] = dis[cur.pos] + 1;pq.push(Point(v,dis[v])); }}}
}int main()
{double maxx = -1;int u,v;cin>>n>>m;while(m--) {scanf("%d%d",&u,&v);vv[u].pb(v);vv[v].pb(u);}Dijkstra(1);ll len = dis[n],shortest = ans[n];//以此为基准
// maxx = max(maxx,(ans[n]*ans[1])*2.0 / shortest);加上就错了maxx = 1;for(int i = 2; i<=n-1; i++) {Dijkstra(i);if(dis[1] + dis[n] == len)maxx = max(maxx,((ans[n]*ans[1])*2.0) / (1.0*shortest));}printf("%.12lf\n",maxx);return 0 ;}
AC代码2:(floyd算法亦可跑最短路条数,和下面附的一个代码类似,只是更新方式不同,他那个直接更新成0,然后下面的那个if中再更新成原值)
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int INF = 0x3f3f3f3f;
const int MAX = 200 + 5;
int maze[MAX][MAX];
ll dp[MAX][MAX];
int main()
{int n,m; int u,v;cin>>n>>m;memset(maze,INF,sizeof maze);while(m--) {scanf("%d%d",&u,&v);maze[u][v] = maze[v][u] = 1;dp[u][v] = dp[v][u] = 1;} double ans = 1.0;for(int k = 1; k<=n; k++) {for(int i = 1; i<=n; i++) {for(int j = 1; j<=n; j++) {if(maze[i][j] == maze[i][k] + maze[k][j]) {dp[i][j] += dp[i][k] * dp[k][j];}else if(maze[i][j] > maze[i][k] + maze[k][j]) {maze[i][j] = maze[i][k] + maze[k][j];dp[i][j] = dp[i][k] * dp[k][j];}}}}for(int i = 2; i<=n-1; i++) {if(maze[1][i] + maze[i][n] == maze[1][n])ans = max(ans,2.0*(dp[1][i]*dp[i][n])/dp[1][n]);}printf("%.12f",ans);return 0 ;}
附: