杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。
Input
第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。
Output
对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".
-----------------------------------------------------------------------------------------------------------------------------------------------------------
根据Floyd的原理,在最外层循环做了k-1次之后,dis[i][j]则代表了i到j的路径中,所有结点编号都小于k的最短路径。
(就是说123456这几个节点做了K=4次后,所有1234之间的最短路径都确定了。当做完k=4次时,至于后面56号,像15、25、36、46等等涉及到5、6号节点的配对,它们之间的路径可能已经求出来了,但还不能确定是不是最短的,只有当k=6都做完了以后,才能知道最终结果。)
由于题目叫我们求至少要经过两个景区 也就是说当前的这个环至少有三个点
现在 对于每一个中间点(k) 我们仍然把它当做一个环的中间点 并且它是编号最大的 因为只有中间点最大 最短路i,j才是最小的(第二行说的)
路程相当于dis[i][k]+dis[k][j]+zdl[i][j](min()保证i与k,k与j肯定都是直接相连的)
看代码了吧(可能有点丑陋 因为改了很久)
#include<bits/stdc++.h>
using namespace std;
//dis -> 原图的距离 zdl ->最短路
const int INF=1000000000;
long long n,m,ans=INF;
long long dis[105][105],zdl[105][105];
void floyd()
{
for(int k=1;k<=n;k++)
{
for(int i=1;i<=k-1;i++)
{
for(int j=1;j<=i-1;j++)
{
ans=min(ans,zdl[i][j]+dis[j][k]+dis[k][i]);
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
zdl[i][j]=min(zdl[i][j],zdl[i][k]+zdl[k][j]);
}
}
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
dis[i][j]=INF;
zdl[i][j]=INF;
}
dis[i][i]=zdl[i][i]=0;
}
for(int i=1;i<=m;i++)
{
long long x,y,v;
cin>>x>>y>>v;
int jj=min(v,dis[x][y]);
dis[x][y]=dis[y][x]=zdl[x][y]=zdl[y][x]=jj;
}
floyd();
if(ans==INF) cout<<"No solution."<<endl;
else cout<<ans<<endl;
return 0;
}
这篇博客介绍了如何应用Floyd算法解决寻找无向图中从A点出发并返回A点,至少经过两个不同景区且不重复的最短路径问题。通过Floyd算法的迭代过程,找到所有节点间最短路径,并解释了为什么中间点取最大编号能确保路径最短。如果无法找到满足条件的路径,则输出'It's impossible.'。

275

被折叠的 条评论
为什么被折叠?



