• 【codevs2011】最小距离之和 [LNOI2013](Floyd)


    题目网址:http://codevs.cn/problem/2011/

    题目大意:有一个图,每次删一条边(可以重复删),求每次删边之后所有点对的最短距离之和。

      看了一眼题目,顿时发现了O(n^4)的暴力解法:每次删边之后跑一次Floyd,然后又看了一眼数据范围,发现n,m<=200……华丽丽的TLE……

      删边……好像不可做……但是如果是加边就好办了。看看能不能把删边转化成加边,于是……正解思路闪现了。

      其实这道题的思路就是把要删掉的边全部先删掉,跑一次Floyd,然后倒着加边,用加上的边更新最短路(设加上的边起点为x,终点为y,看i->x->y->j是否比直接i->j花费更小),就能在O(n^3)的时间内求出答案。

      代码:

    var a:array[0..210,0..210]of longint;
      x,y,z,ans:array[0..210]of longint;
      n,m,i,j,k:longint;
      b:boolean;
    begin
      read(n);
      for i:=1 to n do
        for j:=1 to n do
          read(a[i,j]);//读入图
      read(m);
      for i:=1 to m do begin
        read(x[i],y[i]); z[i]:=a[x[i],y[i]];
        a[x[i],y[i]]:=1<<29;//删边
      end;
      for k:=1 to n do
        for i:=1 to n do
          for j:=1 to n do
            if a[i,j]>a[i,k]+a[k,j] then a[i,j]:=a[i,k]+a[k,j];//跑Floyd
      for i:=m downto 1 do begin
        ans[i]:=0; b:=false;
        for j:=1 to n do begin
          for k:=1 to n do begin
            if a[j,k]>=1<<29 then begin
              ans[i]:=-1; b:=true; break;
            end;
            ans[i]:=ans[i]+a[j,k];
          end;
          if b then break;
        end;//算距离之和
        for j:=1 to n do
          for k:=1 to n do
            if a[j,k]>a[j,x[i]]+z[i]+a[y[i],k] then a[j,k]:=a[j,x[i]]+z[i]+a[y[i],k];//加边,更新答案
      end;
      for i:=1 to m do
        if ans[i]=-1 then writeln('INF')
        else writeln(ans[i]);//输出答案
    end.
    View Code

    注:更新答案时不能用删掉的边直接覆盖掉原边,因为覆盖掉的花费可能更短。

  • 相关阅读:
    用XYNTService把Python程序变为服务
    今天被坑了,而且被坑的好爽! 该死的UTF-8 有 BOM 格式编码
    php 图片上传 500 Internal Server Error 错误
    Linux下 PHP 安装pecl_http方法
    PHP压缩html网页代码原理(清除空格,换行符,制表符,注释标记)
    一段代码让DedeCMS完美兼容PHP5.4
    win7+ oracle +php环境的搭建
    在netbeans下使用调试PHP的插件XdeBug
    使用webbench做压力测试
    ubuntu 13.04 nginx.conf 配置详解
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/6378621.html
Copyright © 2020-2023  润新知