FLOYD算法求最小环及路径输出
两道模板题
1.http://acm.hdu.edu.cn/showproblem.php?pid=1599 这是求最小环的模板题
2.http://poj.org/problem?id=1734 这是输出路径的模板题
由于都是模板题,题意就不再赘述,直接从算法讲起~
FLOYD算法
FLOYD算法是通过类似动态规划的方法求解最短路径问题的高效算法,对于正权值和负权值(不含负环)都有效.该算法主要分为两步:第一步初始化,对于从u到v的边,用邻接矩阵mp[u][v]存储路径的权值,若无这条边则为无穷大(实际写时定成比较大的数即可),第二步状态转移,对于每一对点u,v,枚举是否有点w使得u->w->v的最短路径比u->v的最短路径小,如果是则更新它.
核心的状态转移代码如下:
mp[i][j] = min( mp[i][j], mp[i][k]+mp[k][j] );
求最小环
FLOYD法已求得了到最外层循环k时,所有点对间以点1,2,……,k-1为中间点的最短路径.对于每一个环,这个环可以看为最大编号的点C与其相邻的两个点 A 和B 与 A 到 B 的最短路上的点.因此可以用floyd法拓展.
下面是完整代码:
#include<iostream>
using namespace std;
typedef long long int ll;
const ll inf=1e9;
const ll MAXN=110;
ll mp[MAXN][MAXN],dis[MAXN][MAXN];
ll n,m,u,v,len,mincost,temp,num,s;
void init() {
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
mp[i][j]=inf;
dis[i][j]=inf;
}
}
for(int i=1; i<=m; i++) {
cin>>u>>v>>len;
mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=min(mp[u][v],len);
}
}
void floyd() {
mincost=inf;
for(int k=1; k<=n; k++) {
for(int i=1; i<k; i++) {
for(int j=i+1; j<k; j++) {
temp=dis[i][j]+mp[i][k]+mp[k][j];
if(temp<mincost) {
mincost=temp;
}
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
temp=dis[i][k]+dis[k][j];
if(dis[i][j]>temp) {
dis[i][j]=temp;
}
}
}
}
}
int main() {
while(cin>>n>>m) {
init();
floyd();
if(mincost==inf) cout<<"It's impossible."<<endl;
else cout<<mincost<<endl;
}
return 0;
}
输出最小环路径
我们用一个road[]数组存储输出的最小路径,在每次更新最小环的值时更新这一数组,从开始的点s不断向前推即可.
cnt=0;
s=j;
while(s!=i) {
road[cnt++]=s;
s=p[i][s];
}
road[cnt++]=i;
road[cnt++]=k;
这就是最小环路径的记录部分,注意p[][]数组的初始化,将p[i][j]初始化为i,p[i][j]表示从i到j的路径中经过的第一个点.
下面是完整代码:
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long int ll;
const int inf=1e6;
const int MAXN=110;
int mp[MAXN][MAXN],dis[MAXN][MAXN],road[MAXN],p[MAXN][MAXN];
int n,m,u,v,len,mincost,temp,cnt,s;
void init() {
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
mp[i][j]=inf;
dis[i][j]=inf;
p[i][j]=i;
}
}
for(int i=1; i<=m; i++) {
scanf("%d%d%d",&u,&v,&len);
mp[u][v]=mp[v][u]=dis[u][v]=dis[v][u]=min(mp[u][v],len);
}
}
void floyd() {
mincost=inf;
for(int k=1; k<=n; k++) {
for(int i=1; i<k; i++) {
for(int j=i+1; j<k; j++) {
temp=dis[i][j]+mp[i][k]+mp[k][j];
if(temp<mincost) {
mincost=temp;
cnt=0;
s=j;
while(s!=i) {
road[cnt++]=s;
s=p[i][s];
}
road[cnt++]=i;
road[cnt++]=k;
}
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=n; j++) {
temp=dis[i][k]+dis[k][j];
if(dis[i][j]>temp) {
dis[i][j]=temp;
p[i][j]=p[k][j];
}
}
}
}
}
int main() {
scanf("%d%d",&n,&m);
init();
floyd();
if(mincost>=inf) printf("No solution.");
else {
for(int i=0;i<cnt;i++){
printf("%d ",road[i]);
}
}
return 0;
}