题目链接: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 }