zoukankan      html  css  js  c++  java
  • [模拟赛20180809] 旅程

    题意简述

    给一个有向图,有两个操作,一个是删除一条边,一个是询问两点之间最短路,(n le 200,q le 100000),其中操作一(删边)不超过(200)次。

    一个反向操作的 ( exttt{trick}),相当于先把所有要删的边删除,形成一个新图(mathbf{G}'),对(mathbf{G}')(operatorname{Floyd}),后反向进行加边(( exttt{add Edge}))操作,每次加边更新(f_{i,j})(f_{i,j} = min(f_{i,j},f_{i,u} + f_{v,j} + f_{u,v})),其中((u,v,w))为新加边。

    时间复杂度(mathcal{O}(n^3 + 200n^2))

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 205;
    const long long inf = 5e11;
    int n, m;
    
    struct node
    {
        int opt, x, y;
    };
    
    long long f[N][N], f2[N][N];
    
    int vis[N][N];
    
    long long ans[100005];
    int top = 0;
    
    node q[100005];
    
    void FIO(void)
    {
        freopen("journey.in", "r", stdin);
        freopen("journey.out", "w", stdout);
        return;
    }
    
    void update(int u, int v)
    {
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                f[i][j] = min(f[i][j], f[i][u] + f[v][j] + f[u][v]);
            }
        }
        return;
    }
    
    int main(void)
    {
        FIO();
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                f[i][j] = f2[i][j] = (i == j) ? 0 : inf;
        }
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                scanf("%lld", &f[i][j]);
                f2[i][j] = f[i][j];
            }
        }
        for (int i = 1; i <= m; i++)
        {
            scanf("%d%d%d", &q[i].opt, &q[i].x, &q[i].y);
            if (q[i].opt == 1)
            {
                if (vis[q[i].x][q[i].y] == 0)
                    vis[q[i].x][q[i].y] = i;
                f[q[i].x][q[i].y] = inf;
            }
        }
        for (int k = 1; k <= n; k++)
        {
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)
                {
                    f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
                }
            }
        }
        for (int i = m; i >= 1; i--)
        {
            int u = q[i].x, v = q[i].y;
            if (q[i].opt == 1)
            {
                if (vis[u][v] != i)
                    continue;
                f[u][v] = min(f[u][v], f2[u][v]);
                update(u, v);
            }
            else
            {
                ans[++top] = f[u][v];
            }
        }
        for (int i = top; i >= 1; i--)
            printf("%lld
    ", (ans[i] >= inf) ? -1 : ans[i]);
        return 0;
    }
    
  • 相关阅读:
    MySQL灾备切换
    crontab 定时任务
    Mysql常用命令 详细整理版
    linux 常用命令
    shell逻辑运算总结, 包括[[]]与[]的区别,&&与-a的区别,||与-o的区别
    linux端口详解大全
    编译安装php5.6
    linux给用户添加sudo权限
    Effective C#(二)
    Effective C#(一)
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/lv_cheng.html
Copyright © 2011-2022 走看看