描述
无向图最短路径问题,是图论中最经典也是最基础的问题之一。本题我们考虑一个有 nn 个结点的无向图 GG。
GG 是简单完全图,也就是说 GG 中没有自环,也没有重边,但任意两个不同的结点之间都有一条带权的双向边。
每一条边的边权是非负实数,但我们并不知道每一条边的具体边权。
好消息是我们知道 GG 中任意两点最短路径的长度d(i,j)d(i,j)。且保证至少有一种边权的分配方案满足得到的带权图中ii与jj的最短路长度恰好是d(i,j)d(i,j)。
下面是留给你的任务:对于任意一对点(i,j)(i,j),希望你能找出来所有合法的边权分配方案中ii和jj之间边权的最大值。
格式
输入格式
本题中,每一组数据都有多次询问,每一次询问分别给出了一个无向图GG。
输入的第一行是一个整数 tt,表示总共的询问个数。之后依次给出每一次询问。
对于每一次询问来说,第一行给出了 G 中结点总数 n。之后n行每行有n个整数,给出了一个n×n的矩阵 d,其中第ii行第jj列的整数对应 d(i,j)d(i,j)表示ii到jj的最短路径长度。
因为图GG是简单无向图,对角线元素d(i,i)d(i,i)总是0,且矩形是对称的(也就是说d(i,j)=d(j,i)d(i,j)=d(j,i))。
输出格式
对于每一次询问,若给定的图GG有nn个结点,则输出nn行,每行有nn个整数,描述了一个矩阵 aa。矩阵的第ii行第jj列表示连接ii和jj的边的最大可能边权。如果(i,j)(i,j)的边权可以任意大,则输出字符串infty表示无限。
矩阵的对角线没有实质性意义,请全输出00。因为GG是无向图,所以输出的矩阵aa应该也是对称的(即a(i,j)=a(j,i)a(i,j)=a(j,i))。
不难发现,因为给定的矩阵 dd 中每一个数字都是整数,所以最大可能边权总会是整数。
样例1
样例输入1
2
3
0 2 8
2 0 10
8 10 0
3
0 1 1
1 0 1
1 1 0
样例输出1
0 2 8
2 0 infty
8 infty 0
0 1 1
1 0 1
1 1 0
限制
对于 20\%20% 的数据,有 n = 3n=3。
对于 50\%50% 的数据,有 1≤n≤10。
对于 100\%100% 的数据,有 1≤n≤100,且所有询问中nn的和不超过 800800,对于所有的dd满足1≤d≤256。
每一组数据的时限为 0.5 秒。
题解
这个题挺有意思。
题目大意:给出的是所有两点间的最短路径,要求出图中两点的可能的最大边权,不会对最短路产生影响。
怎么考虑这个问题呢?首先我们把给出的最短路暂定为两条边之间的边权,然后跑floyed,要求是不能只经过一条路到达(即把两点间的最短路抹掉),如果这样得出的两点间的最短路于原来的最短路相等,那么直接连接这两个点的边可以任意大,否则就不变。
怎么能让他不能一条边到达呢?重新开一个数组记录。
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int T,n,d[101][101],m[101][101];
int main()
{
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
scanf("%d",&d[i][j]);
// for (int i=1; i<=n; i++) m[i][i]=0x7fffffff;
memset(m,0x7f,sizeof(m));
for (int k=1; k<=n; k++)
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
if (i!=j&&j!=k&&i!=k)
m[i][j]=min(m[i][j],d[i][k]+d[k][j]);
for (int i=1; i<=n; i++)
for (int j=1; j<=n; j++)
{
if (m[i][j]==d[i][j]&&i!=j) d[i][j]=-1;
}
for (int i=1; i<=n; i++)
{
for (int j=1; j<=n; j++)
if (d[i][j]==-1) printf("infty ");//==和=
else printf("%d ",d[i][j]);
printf("\n");
}
}
return 0;
}
对noip来说,可能不需要那么多的算法。需要做到的是如何独立的思考问题,并将自己的想法转化成代码。同时还要做到认真,细致。