问题 B: 反着来
时间限制: 1 Sec 内存限制: 32 MB提交: 3 解决: 3
[ 提交][ 状态][ 讨论版]
题目描述
相信大家都会解决有向图的最短路问题。这次我们反着来,给你一个有向图中每一对顶点之间的最短路的长度,请你计算出原图中最少可能包含多少条边。
输入
输入的第一行是一个整数T(T<=10),表示有T组测试数据。
每组输入的第一行是一个整数N(1<=N<=100),表示顶点个数。
接下来N行,每行输入N个整数,这些整数都小于10000。
第i行的第j个整数表示从顶点i到顶点j的最短路的长度。
第i行的第i个数字一定是0,其他的数字都大于0。
每组输入的第一行是一个整数N(1<=N<=100),表示顶点个数。
接下来N行,每行输入N个整数,这些整数都小于10000。
第i行的第j个整数表示从顶点i到顶点j的最短路的长度。
第i行的第i个数字一定是0,其他的数字都大于0。
输出
对于每组输入,先输出“Case k: ”,k表示样例的序号,从1开始。然后输出一个整数,表示原图中最少可能包含多少条边。如果原图不存在,则输出“impossible”(引号不输出)。
样例输入
3
3
0 1 1
1 0 1
1 1 0
3
0 1 3
4 0 2
7 3 0
3
0 1 4
1 0 2
4 2 0
样例输出
Case 1: 6
Case 2: 4
Case 3: impossible
题目大意:给你了i到j的最短路长度,请你计算出原图中最少可能包含多少条边。
解题思路:主要算法用的是floyd,用floyd跑一遍;如果出现再次出现最短路径也就是e[i][j]=e[i][k]+e[k][j],说明这条路是多余的把这条路标记出来,然后减去这条路;
如果出现e[i][j]>e[i][k]+e[k][j],说明还有新的最短路,与题目不符合,故不存在;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int t, i, k, j,count,n,flag, x = 0;
int e[110][110];
scanf("%d", &t);
while(t--)
{x++;
flag=0;
scanf("%d", &n);
memset(b,0,sizeof(b));
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
scanf("%d",&e[i][j]);
count=2*n;
for(k=1;k<=n; k++)
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
if(i == j || i == k || k == j)//他们不可以相等
continue;
if(e[i][j]!=-1&&e[i][k]!=-1&&e[k][j]!=-1)
{
if(e[i][j]==e[i][k]+e[k][j])
{
e[i][j]=-1;
count--;
}
if(e[i][j]>e[i][k]+e[k][j])
flag=1;
}
}
if(flag==1)
printf("Case %d: impossible\n", x);
else
printf("Case %d: %d\n", x, count);
}
return 0;
}