AT3535 题解
作者:互联网
题面
思路:
最短路径。
算法实现
我们在这题将要使用 Floyd 算法,至于如何实现,可以先看看【Clear And Present Danger S】这道板子题。
Floyd 算法是一个基于「贪心」、「动态规划」求一个图中所有点到所有点 最短路径的算法,时间复杂度 \(O(n^3)\)
重点思想:以每个点为「中转站」,刷新所有「入度」和「出度」的距离。
重点语句(扭曲):
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(f[i][j]>f[i][k]+f[k][j])
{
f[i][j]=f[i][k]+f[k][j];
}
}
}
}
在此题,我们可以利用表 A 使用 Floyd 算法遍历如果 \(a_{i,j}=a_{i_k}+a_{k,j}\)(其中 i , j 分别为入度和出度 k 是中转点)那就说明表 A 没毛病,标记一下(后面会讲)。
否则“有猫腻”即无解输出 -1 。
Q:为什么要标记呢?
既然相等的话说明出度与入度中间有一个中转点,遍历完了之后只需要统计未被标记的,完事。
CODE:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int a[9999][9999];
bool b[9999][9999];
signed main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int e;
cin>>e;
a[i][j]=e;
}
}
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i!=k&&j!=k&&i!=j)
{
if(a[i][j]==a[i][k]+a[k][j])
{
b[i][j]=1;
}
else
{
if(a[i][j]>a[i][k]+a[k][j])
{
cout<<-1<<'\n';
return 0;
}
}
}
}
}
}
int maxn=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(!b[i][j])
{
maxn+=a[i][j];
}
}
}
cout<<maxn/2<<'\n'; //记得无向图要除以二
return 0;
}
标签:int,题解,出度,入度,9999,AT3535,算法,Floyd 来源: https://www.cnblogs.com/0-SmartBig-0/p/15863973.html