Codeforce 295B Greg and Graph(Floyd的深入理解)

题目链接:http://codeforces.com/problemset/problem/295/B

题目大意:
给出n个点的完全有权有向图,每次删去一个点,求删掉该点之前整张图各个点的最短路之和(包括i->j和j->i)。
解题思路:
这里利用了floyd的性质,下面看一下floyd的写法:
for (k=1;k<=n;k++)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
a[i][j] = min(a[i][j], a[i][k]+a[k][j]);
每次利用点k进行松弛,可以理解为将k点加入图中,所以我们可以倒着加点,如下所示:
for (k=n;k>=1;k--)
for (i=1;i<=n;i++)
for (j=1;j<=n;j++)
a[i][j] = min(a[i][j], a[i][p[k]]+a[p[k]][j]);
每次松弛完顺便记录结果即可。

代码:

 1 #include<bits/stdc++.h>
 2 #define lc(a) (a<<1)
 3 #define rc(a) (a<<1|1)
 4 #define MID(a,b) ((a+b)>>1)
 5 #define fin(name)  freopen(name,"r",stdin)
 6 #define fout(name) freopen(name,"w",stdout)
 7 #define clr(arr,val) memset(arr,val,sizeof(arr))
 8 #define _for(i,start,end) for(int i=start;i<=end;i++)
 9 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
10 using namespace std;
11 typedef long long LL;
12 const int N=1e3+5;
13 const int INF=0x3f3f3f3f;
14 const double eps=1e-10;
15 
16 int p[N];
17 LL mp[N][N];
18 LL ans[N];
19 bool del[N];
20 
21 int main(){
22     FAST_IO;
23     int n;
24     cin>>n;
25     for(int i=1;i<=n;i++){
26         for(int j=1;j<=n;j++){
27             cin>>mp[i][j];    
28         }
29     }
30     for(int i=1;i<=n;i++){
31         del[i]=true;
32         cin>>p[i];
33     }
34     //利用floyd松弛的特性,每次松弛相当于加点,所以直接倒着加点,同时记录结果 
35     for(int k=n;k>=1;k--){
36         int t=p[k];
37         del[t]=false;
38         for(int i=1;i<=n;i++){
39             for(int j=1;j<=n;j++){
40                 mp[i][j]=min(mp[i][j],mp[i][t]+mp[t][j]);
41             }
42         }
43         for(int i=1;i<=n;i++){
44             for(int j=1;j<=n;j++){
45                 if(!del[i]&&!del[j]){
46                     ans[k]+=mp[i][j];
47                 } 
48             }
49         }
50     }
51     for(int i=1;i<=n;i++){
52         cout<<ans[i]<<endl;
53     }
54     return 0;
55 }
原文地址:https://www.cnblogs.com/fu3638/p/9104324.html