图-最短路径问题- Floyd

来源:互联网 发布:php抽奖概率算法 编辑:程序博客网 时间:2024/05/19 05:04

POJ5443兔子与樱花
总时间限制: 1000ms 内存限制: 65535kB
描述
很久很久之前,森林里住着一群兔子。有一天,兔子们希望去赏樱花,但当他们到了上野公园门口却忘记了带地图。现在兔子们想求助于你来帮他们找到公园里的最短路。

输入
输入分为三个部分。
第一个部分有P+1行(P<30),第一行为一个整数P,之后的P行表示上野公园的地点。
第二个部分有Q+1行(Q<50),第一行为一个整数Q,之后的Q行每行分别为两个字符串与一个整数,表示这两点有直线的道路,并显示二者之间的矩离(单位为米)。
第三个部分有R+1行(R<20),第一行为一个整数R,之后的R行每行为两个字符串,表示需要求的路线。
输出
输出有R行,分别表示每个路线最短的走法。其中两个点之间,用->(矩离)->相隔。
样例输入
6
Ginza
Sensouji
Shinjukugyoen
Uenokouen
Yoyogikouen
Meijishinguu
6
Ginza Sensouji 80
Shinjukugyoen Sensouji 40
Ginza Uenokouen 35
Uenokouen Shinjukugyoen 85
Sensouji Meijishinguu 60
Meijishinguu Yoyogikouen 35
2
Uenokouen Yoyogikouen
Meijishinguu Meijishinguu
样例输出
Uenokouen->(35)->Ginza->(80)->Sensouji->(60)->Meijishinguu->(35)->Yoyogikouen
Meijishinguu

思路分析:

显然,这又是一道求每队顶点间最短路的问题。我们观察总共的顶点数目较少,O(n^3)的复杂度是可以接受的。所以我们考虑用Floyd算法。事实上这道题的算法实现时很简单的,但我们要注意如何把实现过程处理得尽量漂亮不容易出错。

细节处理上的小技巧

  • 利用map 来形成名称和位置序号的一一映射
map<string, int>Index;for (int i = 1; i <= P; i++){    cin >> s;    Index[s] = i; }

STL关联容器 map的相关介绍

  • 定义
map<int, string> mapS;  
  • 数据插入
mapStudent.insert(pair<int, string>(1, "s_one"));  mapStudent[3] =  "s_three";//可以覆盖以前关键字对应的值  
  • map的大小
int nSize = mapS.size();  
  • map的遍历
for(iter = mapS.begin(); iter != mapS.end(); iter++)  {      cout<<iter->first<<"   "<<iter->second<<endl;  }  //前向迭代器for(iter = mapS.rbegin(); iter != mapS.rend(); iter++)  {      cout<<iter->first<<"   "<<iter->second<<endl;  }  //反向迭代器for(int nIndex = 0; nIndex < nSize; nIndex++)  {       cout<<mapS[nIndex]<<end;  }  //数组
  • 数据的查找
iter = mapS.find(1); 

floyd算法

void Floyd(){    for (int k = 1; k <= P; k++)//第k次迭代        for (int i = 1; i <= P; i++)            if (i != k)            for (int j = 1; j <= P; j++)            if (j != k && f[i][k] + f[k][j] < f[i][j])            //如果从i到j的路径上经过了k同时经过k的那条路径比原来的路径短            {                f[i][j] = f[i][k] + f[k][j];//更新路径长度                g[i][j] = g[i][k];//i到j路径上i的后继            }}
  • 注意维护从i到j路径上的后继节点

初始化过程

scanf("%d", &P);    for (int i = 1; i <= P; i++)    {        cin >> s;        Index[s] = i; Name[i] = s;    }    for (int i = 1; i <= P; i++)        for (int j = 1; j <= P; j++)            f[i][j] = INF;    for (int i = 1; i <= P; i++) f[i][i] = 0;    for (int i = 1; i <= Q; i++)    {        int d;        cin >> s >> t; scanf("%d", &d);        int u = Index[s], v = Index[t];        if (d < f[u][v]) f[u][v] = f[v][u] = d;        //注意一下万一有重复输入        g[u][v] = v; g[v][u] = u;        //注意一下无向图    }

注意点:
1.map容器的插入
2.注意是无向图
3.注意处理重复输入等特殊情况

Query过程

scanf("%d", &R);    for (int i = 1; i <= R; i++)    {        cin >> s >> t;        int u = Index[s], v = Index[t];        Query(u, v);    }
void Query(int u, int v)//访问u{    for (int w = u; w != v; w = g[w][v])    {        cout << Name[w] << "->(" << f[w][g[w][v]] << ")->";    }    cout << Name[v] << endl;}

POJ9200社交网络

#include <iostream>using namespace std;int N;const int MaxN = 305;int M[MaxN][MaxN];void Floyd(){    for(int k = 1; k <= N;  k++)        for(int i = 1; i <= N; i++)            for(int j = 1; j <= N; j++)                if(M[i][k] == 1 && M[k][j] == 1)                    M[i][j] = 1;}int main(){#ifndef ONLINE_JUDGE    freopen("input.txt", "r", stdin);    freopen("output.txt", "w", stdout);#endif    scanf("%d", &N);    cin.get();    for(int i = 1; i <= N; i++)    {        for(int j = 1; j <= N; j++)        {            M[i][j] = cin.get()-'0';            //printf("%d ",M[i][j]);        }        //printf("\n");        cin.get();    }    Floyd();    for(int i = 1; i <= N; i++)    {        for(int j = 1; j <= N; j++)        {            printf("%d",M[i][j]);        }        printf("\n");    }#ifndef ONLINE_JUDGE    fclose(stdin); fclose(stdout);#endif    return 0;}

简单Floyd 注意点 输入数据的时候的cin.get()应用

原创粉丝点击