其他分享
首页 > 其他分享> > AT3535 题解

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