AtCoder Regular Contest 083 D: Restoring Road Network

题意

有一张无向带权连通图(点数<=300),给出任意两点i,j之间的最短路长度dis[i][j].问是否存在一张这样的无向图.如果不存在输出-1.如果存在输出所有这样的无向图中边权和最小的一张的边权和.

分析

如果存在i,j,k(i,j,k互不相同)使得dis[i][k]+dis[k][j]<dis[i][j]那么一定不存在.否则一定存在.
对于i,j(i!=j),如果存在第三个点k使得dis[i][k]+dis[k][j]=dis[i][j],那么为了总的边权和最小,i和j必然没有连边,i和j之间的最短路径是从i到k的最短路径和k到j的最短路径连接起来得到的.
如果不存在这样的k,i和j之间必然存在一条边权为dis[i][j]的边.
O(n^3)完事了.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=305;
int dis[maxn][maxn];
bool notneed[maxn][maxn];
int main(){
  int n;scanf("%d",&n);
  for(int i=1;i<=n;++i){
    for(int j=1;j<=n;++j){
      scanf("%d",&dis[i][j]);
    }
  }
  bool flag=true;
  for(int i=1;i<=n;++i){
    for(int j=1;j<=n;++j){
      for(int k=1;k<=n;++k){
    if(i!=j&&j!=k&&k!=i){
      if(dis[i][j]+dis[j][k]<dis[i][k])flag=false;
      if(dis[i][j]+dis[j][k]==dis[i][k])notneed[i][k]=true;
    }
      }
    }
  }
  if(!flag){
    printf("-1\n");
  }else{
    long long ans=0;
    for(int i=1;i<=n;++i){
      for(int j=i+1;j<=n;++j){
    if(!notneed[i][j])ans+=dis[i][j];
      }
    }
    printf("%lld\n",ans);
  }
  return 0;
}

转载于:https://www.cnblogs.com/liu-runda/p/7533135.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值