codeforces 295B Greg and Graph [Floyed]

Greg and Graph
Time Limit: 3000MS Memory Limit: 262144KB 64bit IO Format: %I64d & %I64u
Submit

Status

Description
Greg has a weighed directed graph, consisting of n vertices. In this graph any pair of distinct vertices has an edge between them in both directions. Greg loves playing with the graph and now he has invented a new game:

The game consists of n steps.
On the i-th step Greg removes vertex number xi from the graph. As Greg removes a vertex, he also removes all the edges that go in and out of this vertex.
Before executing each step, Greg wants to know the sum of lengths of the shortest paths between all pairs of the remaining vertices. The shortest path can go through any remaining vertex. In other words, if we assume that d(i, v, u) is the shortest path between vertices v and u in the graph that formed before deleting vertex xi, then Greg wants to know the value of the following sum: .
Help Greg, print the value of the required sum before each step.

Input
The first line contains integer n (1 ≤ n ≤ 500) — the number of vertices in the graph.

Next n lines contain n integers each — the graph adjacency matrix: the j-th number in the i-th line aij (1 ≤ aij ≤ 105, aii = 0) represents the weight of the edge that goes from vertex i to vertex j.

The next line contains n distinct integers: x1, x2, …, xn (1 ≤ xi ≤ n) — the vertices that Greg deletes.

Output
Print n integers — the i-th number equals the required sum before the i-th step.

Please, do not use the %lld specifier to read or write 64-bit integers in C++. It is preferred to use the cin, cout streams of the %I64d specifier.

Sample Input
Input
1
0
1
Output
0
Input
2
0 5
4 0
1 2
Output
9 0
Input
4
0 3 1 1
6 0 400 1
2 4 0 1
1 1 1 0
4 1 2 3
Output
17 23 404 0
Source
Codeforces Round #179 (Div. 1)
題意:對給定圖按給定順序刪邊,求每次刪邊之前聯通的點對的最小距離的和。
分析:考慮反向加邊,則每加一個點做一次鬆弛操作,題目所求的就是動態的當時聯通的點的最小距離和,在枚舉的時候加上已被加上的點的最小距離即可,注意,即使枚舉到有的點沒有被加上也要更新它的最小值,因爲它在該點後被加上,在那時可以被該點鬆弛。(當然,之前的點也可以被鬆弛,因爲求的最小值是當前情況,邊不存在先後。)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=505;
int n,orde[maxn],f[maxn][maxn],vit[maxn];
long long ans[maxn]; 
void init()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&f[i][j]);
    for(int i=1;i<=n;i++)
        scanf("%d",&orde[i]);
}
void work()
{
    for(int i=n;i>=1;i--){
        vit[orde[i]]=1;
        for(int j=1;j<=n;j++)
            for(int k=1;k<=n;k++){
                f[j][k]=min(f[j][k],f[j][orde[i]]+f[orde[i]][k]);
            if(vit[j]&&vit[k]&&f[j][k]!=2e8)ans[i]+=(long long)f[j][k];
            }
    }
    for(int i=1;i<=n;i++)
        printf("%I64d ",ans[i]);
}
int main()
{
    freopen("codeforces295B.in","r",stdin);
    freopen("codeforces295B.out","w",stdout);
    init();
    work();
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章