POJ 2472 106 miles to Chicago(Dijstra变形——史上最坑的最长路问题)

时间:2023-03-10 01:19:09
POJ 2472 106 miles to Chicago(Dijstra变形——史上最坑的最长路问题)

题目链接 :
http://poj.org/problem?id=2472

Description

In the movie "Blues Brothers", the orphanage where Elwood and Jack were raised may be sold to the Board of Education if they do not pay 5000 dollars in taxes at the Cook Country Assessor's Office in Chicago. After playing a gig in the Palace Hotel ballroom to earn these 5000 dollars, they have to find a way to Chicago. However, this is not so easy as it sounds, since they are chased by the Police, a country band and a group of Nazis. Moreover, it is 106 miles to Chicago, it is dark and they are wearing sunglasses.
As they are on a mission from God, you should help them find the
safest way to Chicago. In this problem, the safest way is considered to
be the route which maximises the probability that they are not caught.

Input

The input contains several test cases.

Each test case starts with two integers n and m (2 <= n <= 100
, 1 <= m <= n*(n-1)/2). n is the number of intersections, m is
the number of streets to be considered.

The next m lines contain the description of the streets. Each street
is described by a line containing 3 integers a, b and p (1 <= a, b
<= n , a != b, 1 <= p <= 100): a and b are the two end points
of the street and p is the probability in percent that the Blues
Brothers will manage to use this street without being caught. Each
street can be used in both directions. You may assume that there is at
most one street between two end points.

The last test case is followed by a zero.

Output

For
each test case, calculate the probability of the safest path from
intersection 1 (the Palace Hotel) to intersection n (the Honorable
Richard J. Daley Plaza in Chicago). You can assume that there is at
least one path between intersection 1 and n.

Print the probability as a percentage with exactly 6 digits after
the decimal point. The percentage value is considered correct if it
differs by at most 10-6 from the judge output. Adhere to the format
shown below and print one line for each test case.

Sample Input

5 7
5 2 100
3 5 80
2 3 70
2 1 50
3 4 90
4 1 85
3 1 70
0

Sample Output

61.200000 percent
题意描述:
  输入顶点数和边的条数以及从无向边,不同的是表示从a到b不被抓住的概率是p
计算并输出从1到n他们不被抓住的最大概率
解题思路:
  首先单源最长路问题,Dijstra再合适不过了,但是套模板的话,多半是会错的,因为涉及一点数学概率知识。但是使用求最短路的Flyod算法敲模板也能过。
先说一下Dijstra算法涉及的一点点数学概率知识。
  一般来说我们使用Dijstra算法求最短路问题,dis数组存储的是1号顶点到其他各个顶点的直接距离,这个是固有属性,不管之前的点是哪个,只要
要使用该点,那么该点到各个顶点的距离不会因为之前使用的顶点而改变,但是,但是本题求的是不被抓住的最大概率,它由多个事件达成,换句话说,使用事件发生的概率乘法计数原理时,
之前的时间发生会影响后续事件发生的概率。
  所以我们初始化dis数组时,应该除了1号顶点置为1以外(因为走到1号顶点的概率是百分之百),其他先置为0,因为只有走到某个顶点了,再将该顶点到其他各顶点的距离进行一个更新。
剩下的就是使用Dijstra算法变形求解最长路啦。
上代码:
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
using namespace std;
const int inf=; double map[][];
int main()
{
int n,m,i,j,u,v;
int a,b;
int book[];
double c,p[];
while(scanf("%d",&n), n != )
{
scanf("%d",&m);
memset(map,,sizeof(map));
for(i=;i<=m;i++)
{
scanf("%d%d%lf",&a,&b,&c);
map[a][b]=map[b][a]=c/;
}
memset(book,,sizeof(book));
book[]=;
memset(p,,sizeof(p));
p[]=;
for(i=;i<=n-;i++)
{
u=;
double maxp=;
for(j=;j<=n;j++)
{
if(!book[j] && p[j] > maxp)
{
maxp=p[j];
u=j;
}
}
book[u]=;
for(v=;v<=n;v++)
{
if(p[v] < p[u]*map[u][v])
p[v]=p[u]*map[u][v];
}
}
printf("%.6lf percent\n",p[n]*100.0);
}
return ;
}

再说一下Flyod算法,使用这个算法直接跑的话,因为是最先加入一个点进行松弛,事情也是连续的,也是遵循乘法原理的。

#include<cstdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
#include<algorithm>
using namespace std;
const int inf=; double map[][];
int main()
{
int n,m,i,j,k;
int a,b;
double c;
while(scanf("%d",&n), n != )
{
scanf("%d",&m);
memset(map,,sizeof(map));
for(i=;i<=m;i++)
{
scanf("%d%d%lf",&a,&b,&c);
map[a][b]=map[b][a]=c/;
}
for(k=;k<=n;k++)
for(i=;i<=n;i++)
for(j=;j<=n;j++)
if(map[i][j] < map[i][k] * map[k][j])
map[i][j] = map[i][k] * map[k][j];
printf("%.6lf percent\n",map[][n]*);
}
return ;
}