upc 消失的无向图

时间限制: 1 Sec 内存限制: 128 MB

题目描述

从前有一张n个点的无向图,边权都是正整数。但现在所有的边都消失了,只留下任意两点之间的最短路。

你现在想知道,所有边的边权和至少是多少。

输入

第一行一个正整数n 。
接下来一个n×n的矩阵A ,其中Ai,j代表原来图中i到j的最短路。
保证Ai,i=0,Ai,j=Aj,i。

输出

一行一个整数,表示答案。
如果不存在任何连边方案满足所有的最短路限制,输出-1 。

样例输入
3
0 1 3
1 0 2
3 2 0
样例输出
3
提示

对于30%的数据,n≤7。
对于另外30%的数据,保证存在一种最优解,满足原图是一条链。
对于100%的数据,满足n≤300,1≤Ai,j≤109,(i≠j) 。

思路

判断dis[ i ] [ j ]与dis[ i ] [ k ] + dis[ k ] [ j ]的关系。
如果dis[ i ] [ j ] > dis[ i ] [ k ] + dis[ k ] [ j ] ,说明不满足任何连边方案满足所有的最短路限制,输出 - 1。
如果等于就说明这条边是可以省略删去的,标记一下。
最后将所有未标记的边加起来,结果除以2(因为正反加了两遍)

代码:

#include<iostream>
#include<string>
#include<map>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
const double eps=0.01;
const int N=310;
const int mod=1000000007;
ll ans,dis[N][N],n;
bool vis[N][N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++) 
    scanf("%d",&dis[i][j]);
    for(int k=1;k<=n;k++)
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
    {
        if(k==i||i==j||k==j) continue;
        if(dis[i][j]>dis[i][k]+dis[k][j]) 
        {
            printf("-1");
            return 0;
        }
        if(dis[i][j]==dis[i][k]+dis[k][j]) vis[i][j]=1;
    }
    for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++) 
    {
        if(!vis[i][j])
        { 
            ans+=dis[i][j];
        }
    }
    printf("%lld",ans/2);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值