以下是问题链接:http://codeforces.com/contest/295/problem/B
Greg有一个称重的有向图,由n个顶点组成。在该图中,任何一对不同的顶点在两个方向上都具有边缘。 Greg喜欢玩图表,现在他发明了一款新游戏:
游戏包含n个步骤。 在第i步,Greg从图中移除顶点数xi。当Greg移除顶点时,他还会移除进出该顶点的所有边。 在执行每个步骤之前,Greg想要知道所有剩余顶点对之间的最短路径的长度总和。最短路径可以通过任何剩余的顶点。 帮助Greg,在每一步之前打印所需总和的值。
输入:
第一行包含整数n(1≤n≤500) - 图中顶点的数量。
接下来n行每行包含n个整数 - 图形邻接矩阵:第i行中的第j个数aij(1≤aik≤105,aii = 0)表示从顶点i开始的边的权重到顶点j。
下一行包含n个不同的整数:x1,x2,...,xn(1≤xi≤n) - Greg删除的顶点。
输出:
打印n个整数 - 第i个数字等于第i步之前所需的总和。
所以,基本上我的方法是在删除任何顶点之前运行Floyd-Warshall算法,并且为了删除,我只需要在两行的邻接矩阵中将要删除的顶点的值设置为INT_MAX
和列。
基本上,此循环位于main
for (int h = 0; h < n; h++)
{
func();
int val = arr[h]; // arr contains the vertices to be deleted
for ( i = 1; i <= n; i++ )
dist[val][i] = INT_MAX;
for ( i = 1; i <= n; i++ )
dist[i][val] = INT_MAX;
}
这是我对Flloyd Warshall算法的实现:
void func ()
{
//int i,j,k;
ans = 0;
for ( i = 1; i <= n; i++ )
{
for ( j = 1; j <= n; j++ )
{
if (i == j)
val[i][j][0] = 0;
else if (dist[i][j] != 0)
val[i][j][0] = dist[i][j];
else
val[i][j][0] = INT_MAX;
}
}
for (k = 1; k <= n; k++)
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
val[i][j][k] = min(val[i][j][k-1],val[i][k][k-1]+val[k][j][k-1]);
//int ans = 0;
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
ans = ans + val[i][j][n];
cout<<ans<<"\t";
}
这里,val
是我创建的全局三维矩阵,arr
包含要删除的顶点。但是,当我运行这个逻辑时,它最初只给出正确的答案,即没有删除任何顶点时。但在那之后,它给出了错误的价值。我不明白为什么?我的逻辑是不正确的?
答案 0 :(得分:1)
一件看起来很奇怪的事情是,最后你要计算所有剩余顶点对的总和,但你的循环只是在所有顶点上:
for ( i = 1; i <= n; i++ )
for ( j = 1; j <= n; j++ )
ans = ans + val[i][j][n];
答案 1 :(得分:0)
这是错误的方法,将获得TLE...。 按照这种方式
U应该牢记对floyd warshall算法的理解。
首先要弄清楚自己,然后讲到这一点,按照这种算法,您可以按任何顺序设计中间元素(k)。因此,这里有n个步骤,这意味着将按给定的顺序删除n个节点……这意味着您可以按此给定的顺序设计您的中间元素..说给定的删除顺序集为[1,2,3]………………。
现在这意味着当删除1个顶点时,则每对最短路径的总和。然后,当2也被删除时,依此类推…………
现在以这种方式思考,当仅考虑删除不包含3的所有顶点时,在这里使用k(3)时,您可以求和剩下3个的总和,现在使k的值为(2)意味着仅2和剩下的3个现在被删除,现在求和........因此,如果u反转此答案,则当1 2 3剩余时,求和(不删除顶点),则1个被删除
这意味着几乎只有2,3个剩余的被删除,它们加起来…………。
所以,如果您对floyd warshall算法有个好主意,我认为这应该很清楚
基于上述想法,我在这里干净整洁的解决方案