http://poj.org/problem?id=3613
题意:
求从一个点s 到 一点 e 经过 n 条边的最短路经是多少(可以有重边):
看到很难多解题报告说的是n 个点 ,其实,n 条边 应该是 n - 1 个点
题解:
我们知道线性代数中有:
在只 含有 01邻接矩阵
A的
K次 方
C=A^K,
C[i][j]表示
i点到
j点正好经过
K条边的路径数。
而floyd则是每次使用一个中间点k去更新i,j之间的距离,那么更新成功表示i,j之间恰有一个点k时的最短路,如果做N - 1次floyd那么不就是i,j之间借助N - 1 个点时的最短路了
当 c[i][j] > a[i][k] + a[k][j] 则更新
第二次将c[i][j]拷贝回到a[i][j]当中,并将c[i][j]重新置为INF,再做一次,则是在原来的基础上在i,j之间再用一个点k来松弛,这时候i,j之间实际上已经是两个点了,
但是这个题的 n (边数太大)我们要用到 倍增法,其实即使 二分思想 例如 经过 5 条边 把 (4 个点) == 两个 2 条边的 松驰一次 ;
1 #include<cstdio>
2 #include<cstring>
3 #include<cmath>
4 #include<iostream>
5 #include<algorithm>
6 #include<
set>
7 #include<map>
8 #include<queue>
9 #include<vector>
10 #include<
string>
11
#define Min(a,b) a<b?a:b
12
#define Max(a,b) a>b?a:b
13
#define CL(a,num) memset(a,num,sizeof(a));
14
#define maxn 40
15
#define eps 1e-6
16
#define inf 100000000
17
#define mx 1<<60
18
#define ll __int64
19
using
namespace std;
20 map<
int ,
int>map1;
21
int num ;
22
struct matrix
23 {
24
int m[
210][
210];
25
void clear()
26 {
27 memset(m,
0x3f,
sizeof(m));//错在这好几次 ,貌似这道题的 数很大 我的 inf 开的不够大
28
/*
for(int i = 0; i < 210 ;i++)
29
{
30
for(int j = 0 ; j < 210 ;j++)
31
m[i][j] = inf;
32
}
*/
33 }
34 };
35
36 matrix floyd(matrix a,matrix b)
37 {
38
39 matrix dis;
40 dis.clear();
41
int i,j,k;
42
for(k =
0; k < num;k++)//一次floyd 是找到一个中间点
43
for(i =
0 ; i < num;i++ )
44 {
45
for(j =
0;j < num;j++)
46 {
47
48
if(dis.m[i][j] > a.m[i][k] + b.m[k][j])
49 {
50 dis.m[i][j] = a.m[i][k] + b.m[k][j] ;
51
//
printf("%d %d %d ++++\n",dis.m[i][j],i , j);
52
53
54 }
55
56 }
57 }
58
59
return dis;
60 }
61 matrix solve(matrix a,
int k)
62 {
63
if(k ==
0)
return a;
64 matrix ans ;
65
66 ans = a ;
67
68
while(k)
69 {
70
71
if(k&
1)
72 {
73 ans = floyd(ans,a);
74
75 }
76 a = floyd(a,a);
77
78
79 k>>=
1;
80 }
81
return ans ;
82 }
83
int main()
84 {
85
int t,n,m,s,e,x,y,len,i;
86 matrix a;
87
while(scanf(
"
%d%d%d%d
",&n,&t,&s,&e)!=EOF)
88 {
89 num =
0;
90 map1.clear() ;
91 a.clear() ;
92
93
for(i =
0; i < t;i++)
94 {
95 scanf(
"
%d %d %d
",&len,&x,&y);
96
if(map1.find(x)==map1.end()) map1[x] = num ++;
97
if(map1.find(y)==map1.end()) map1[y] = num ++;
98
int x1 = map1[x];
99
int y1 = map1[y];
100
101
if(len < a.m[x1][y1])
102 {
103
104 a.m[x1][y1] = a.m[y1][x1] = len ;
105
106
107 }
108
109
110 }
111
112
int j;
113
114
115 a = solve(a,n -
1);// n 条边 ,经过 n-1 个点
116
117
/*
for(i = 0; i < num;i++)
118
{
119
for(j = 0; j < num;j++)
120
{
121
printf("%d ",a.m[i][j]);
122
}
123
124
printf("\n");
125
126
}
*/
127
128 printf(
"
%d\n
",a.m[map1[s]][map1[e]]) ;
129
130 }
131 }