Greg and Graph

这题是每次删一次点并输出操作前的值,将其转化成删掉所有点然后依次存入一个点,再进行佛罗里达,最后将值倒过来输出就好

点击查看代码
/* 台州第一深情 */
#include <bits/stdc++.h>
using namespace std;
using i64 = long;
using ll = long long;
typedef pair<int, int> PII;
const int N = 5e2 + 5;
const int M = 1e6;
int vis[M];//vis:判断当前点是否添加进去了
int s, f;
ll a[N][N], b[M];
int n, m;
int p[N];//依次存入需要进行操作的点
ll ans[N];//存值
void build()
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
            {
                a[i][j] = 0;
            }
            else
            {
                a[i][j] = 1e7;
            }
        }
    }
}
void floyd()
{
    for (int tiao = 1; tiao <= n; tiao++)
    {
        for (int from = 1; from <= n; from++)
        {
            for (int to = 1; to <= n; to++)
            {
                a[from][to] = min(a[from][tiao] + a[tiao][to], a[from][to]);
            }
        }
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            cin >> a[i][j];//有向图存单边值
        }
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> p[i];
        vis[p[i]]++;//存入点,假装这些点从来没有过
    }

    for (int i = n; i >= 1; i--)//因为是输入时是顺序删除,所以要倒过来存点
    {
        vis[p[i]] = 0;//当前点加进来了
        for (int j = 1; j <= n; j++)
        {
            for (int k = 1; k <= n; k++)
            {
                a[j][k] = min(a[j][k], a[j][p[i]] + a[p[i]][k]);//否罗里达,将存入的点当成跳点,然后进行最小值判断
                if (!vis[k] && !vis[j])
                {
                    ans[i] += a[j][k];//如果当前两个点都已经加进来了,就把他们存入当前操作的ans来
                }
            }
        }
    }
    for (int i = 1; i <= n; i++)//存点是倒过来存,输出要正序输出
    {
        cout << ans[i] << ' ';
    }
    return 0;
}
posted @ 2024-07-09 19:42  台州第一深情  阅读(4)  评论(0编辑  收藏  举报