Codeforces Round #179 (Div. 2)D. Greg and Graph【floyd变形】
http://codeforces.com/contest/296/problem/D
在讲这道题之前我先现简要介绍一下Floyd—Warshall算法,方便大家更好的了解这道题。
Floyd—Warshall算法的原理是动态规划。
设D[i][j][k]为从i到j只以1~k中节点为中间结点的最短路径长度,则:
(1)若最短路径经过点k,那么D[i][j][k]=D[i][k][k-1]+D[k][j][k-1]
(2)若最短路径不经过点k,那么D[i][j][k]=D[i][j][k-1]
因此D[i][j][k]=min(D[i][k][k-1]+D[k][j][k-1],D[i][j][k]=D[i][j][k-1]).
如果我们把k放在最外层的循环,那么第三位在实现上可以省去。
这道题可以反着思考,我们考虑从一个点开始一个个添加,那么答案倒着输出就行了。
我们每次加进来的点相当于k,首先需要进行一个双重循环找到k点和所有点之间的最短路径;然后就以k点位判断节点更新之前的k-1个点,时间复杂度降到O(n^3),而暴力解法每次都要进行floyd,时间复杂度为O(n^4);相比之下前述解法考虑到了floyd算法的性质,更好了运用了算法的内质。
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <cmath> #include <queue> using namespace std; template <class T> void checkmin(T &t,T x) {if(x < t) t = x;} template <class T> void checkmax(T &t,T x) {if(x > t) t = x;} template <class T> void _checkmin(T &t,T x) {if(t==-1) t = x; if(x < t) t = x;} template <class T> void _checkmax(T &t,T x) {if(t==-1) t = x; if(x > t) t = x;} typedef pair <int,int> PII; typedef pair <double,double> PDD; typedef long long ll; #define foreach(it,v) for(__typeof((v).begin()) it = (v).begin(); it != (v).end ; it ++) int n ; const int N = 555; int g[N][N]; ll ans[N]; int a[N]; int main() { cin >> n; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin >> g[i][j]; for(int i=n;i>=1;i--) cin >> a[i]; ans[1] = 0; for(int i=2;i<=n;i++) { int aa = a[i]; ans[i] += ans[i-1]; for(int j=1;j<i;j++) ans[i] += g[a[i]][a[j]] + g[a[j]][a[i]]; for(int j=1;j<i;j++) for(int k=1;k<i;k++) { if(g[a[j]][a[i]] > g[a[j]][a[k]]+g[a[k]][a[i]]) { ans[i] -= g[a[j]][a[i]]; ans[i] += g[a[j]][a[k]]+g[a[k]][a[i]]; g[a[j]][a[i]] = g[a[j]][a[k]]+g[a[k]][a[i]]; } if(g[a[i]][a[j]] > g[a[i]][a[k]] + g[a[k]][a[j]]) { ans[i] -= g[a[i]][a[j]]; ans[i] += g[a[i]][a[k]] + g[a[k]][a[j]]; g[a[i]][a[j]] = g[a[i]][a[k]] + g[a[k]][a[j]]; } } for(int j=1;j<i;j++) for(int k=1;k<i;k++) { if(g[a[j]][a[k]] > g[a[j]][a[i]] + g[a[i]][a[k]]) { ans[i] -= g[a[j]][a[k]]; ans[i] += g[a[j]][a[i]] + g[a[i]][a[k]]; g[a[j]][a[k]] = g[a[j]][a[i]] + g[a[i]][a[k]]; } } } cout << ans[n]; for(int i=n-1;i>=1;i--) cout << " "<< ans[i]; cout << endl; return 0; }