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;
}

 

posted @ 2013-04-12 03:16  aiiYuu  阅读(460)  评论(2编辑  收藏  举报