Floyd最小环理解+模板:
https://www.cnblogs.com/DF-yimeng/p/8858184.html
除了上述博文里写的,我再补充几点我的理解。
1.为什么先枚举ij求经过ijk的最小环再更新k?
因为更新了K点,dis[i][j]可能会经过K,那么再枚举ij求ijk可能会得到来回相同的路,那么就不是环了。
2.为什么需要两个数组?
一个数组dis[][]表示的是正常从u到v经过k的最短路,
另一个数组mp[][]表示的是不经过k的时候回来的时候的最短路。
通过mp[][]找与k相邻的两个点到k的距离,如下图的情况即找x2和x3到k的距离。通过dis[][]找到与k相邻两点之间的最短距离,如下图的情况即找x2->x3的最短距离。
x1->x2->k->x3->...->x9
HDU1599
https://vjudge.net/problem/HDU-1599
Input第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。Output对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".Sample Input
3 3
1 2 1
2 3 1
1 3 1
3 3
1 2 1
1 2 3
2 3 1
Sample Output
3
It's impossible.
#include<bits/stdc++.h>
using namespace std;
const int inf=1e8;
const int maxn=;
int dis[maxn][maxn];//表示的正常从u到v经过k的最短路
int mp[maxn][maxn];//表示的是不经过k的时候回来的时候的最短路
int n,m,u,v,w;
int i,j,k;
void floyd()
{
int minn=inf;
for(k=;k<=n;k++)
{
for(i=;i<k;i++)
for(j=i+;j<k;j++)
minn=min(minn,dis[i][j]+mp[j][k]+mp[k][i]);
for(i=;i<=n;i++)
for(j=;j<=n;j++)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
if(minn==inf)
cout<<"It's impossible."<<endl;
else
cout<<minn<<endl;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
for(i=;i<=n;i++)
for(j=;j<=n;j++)
mp[i][j]=dis[i][j]=inf;
//memset(mp,0x3f,sizeof mp);
for(i=;i<=m;i++)
{
cin>>u>>v>>w;
mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=min(w,mp[u][v]);
}
floyd();
}
return ;
}
思路:
floyd最小环的模板题。
注意点:
一开始把无穷值设为0x3f3f3f3f,WA了。把值改为1e8或者1e7(>1000(道路最大数)*100(站点最大数))就能AC,至今不明原因。(>人<;)