POJ 3613 FLOYD+倍增

题意:

求S到T的经过k条路径的最短路

(这题出的真心好)

思路:

设d[i][j][k]为从i到j经过k条边的最短路,则d[i][j][k]=d[i][p][k/2]+d[p][j][k/2]

利用倍增加速floyd

其实说实话矩阵乘法和floyd真心很像,直接写成矩阵乘法的格式了~

PS:读入边的时候,第一个元素是边权,我纠结了半天,怎么看图也不连通。。。。

View Code
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <iostream>
 5 #include <map>
 6 
 7 #define N 200 
 8 
 9 using namespace std;
10 
11 map<int,int> mp;
12 
13 struct MATRIX
14 {
15     int mt[N][N];
16 }dg,fb;
17 
18 int n,m,S,T,cnt;
19 
20 inline MATRIX operator +(MATRIX a,MATRIX b)
21 {
22     MATRIX c;
23     memset(c.mt,0x3f,sizeof c.mt);
24     for(int k=1;k<=cnt;k++)
25         for(int i=1;i<=cnt;i++)
26             for(int j=1;j<=cnt;j++)
27                 if(c.mt[i][j]>a.mt[i][k]+b.mt[k][j])
28                     c.mt[i][j]=a.mt[i][k]+b.mt[k][j];
29     return c;
30 }
31 
32 void read()
33 {
34     mp.clear(); cnt=0;
35     memset(dg.mt,0x3f,sizeof dg.mt);
36     memset(fb.mt,0x3f,sizeof fb.mt);
37     for(int i=1,a,b,sa,sb,sd;i<=m;i++)
38     {
39         scanf("%d%d%d",&sd,&sa,&sb);
40         if(!mp[sa]) mp[sa]=++cnt;
41         if(!mp[sb]) mp[sb]=++cnt;
42         a=mp[sa]; b=mp[sb];
43         if(sd<dg.mt[a][b]) dg.mt[b][a]=dg.mt[a][b]=sd;
44     }
45     for(int i=1;i<=cnt;i++) fb.mt[i][i]=0;    
46 }
47 
48 void go()
49 {
50     while(n)//倍增 
51     {
52         if(n&1) fb=fb+dg;
53         dg=dg+dg;
54         n>>=1;
55     }
56     printf("%d\n",fb.mt[mp[S]][mp[T]]);
57 }
58 
59 int main()
60 {
61 
62     while(scanf("%d%d%d%d",&n,&m,&S,&T)!=EOF)
63     {
64         read();
65         go();
66     }
67     return 0;
68 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2718999.html