题目链接:http://soj.me/1031
题目大意:可以把题目看成是求无向网的最短路径问题,顶点用字符串表示。
算法实现:
首先输入的边数最多有100条,最坏情况下最多有200个顶点,这一个很小的数,我们可以用最简单的方法做:Floyd算法,时间复杂度是O(n^3)。虽然Floyd算法是用来求有向图的,但是我们可以把无向图看成有向图,只是每条边都是双向的而已。
对于顶点是字符串的处理:可以用STL的map。定义一个map,以顶点的名称作为键值(下标),以这个顶点出现的顺序序号作为对应的值。
需要注意的地方:可能会问你两个从未过的地方之间的最短路径的距离,如果它们不同,输出-1,相同则输出0。
#include<iostream>
#include<cstdio>
#include<string>
#include<map>
#define INF 100000
#define get_min(a,b) ((a)<(b)?(a):(b))
using namespace std;
map<string,int> c;
int g[201][201];
void floyd(int n)
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
if (g[i][k] < INF)
for (int j = 1; j <= n; j++)
if (g[k][j] < INF)
g[i][j] = get_min(g[i][j], g[i][k] + g[k][j]);
}
int main()
{
int C;
cin>>C;
while(C--)
{
for(int i=1;i<=200;i++)
for(int j=1;j<=200;j++)
if(i!=j) g[i][j]=INF;
else g[i][j]=0;
int N,cnt=0;
cin>>N;
c.clear();
for(int i=1;i<=N;i++)
{
int v1,v2,dis;
string str1,str2;
cin>>str1>>str2>>dis;
if(c.find(str1)==c.end())
c.insert(make_pair(str1,++cnt));
if(c.find(str2)==c.end())
c.insert(make_pair(str2,++cnt));
v1=c[str1];
v2=c[str2];
g[v1][v2]=g[v2][v1]=dis;
}
floyd(cnt);
string S,T;
cin>>S>>T;
if(S==T) cout<<0<<endl;
else if(c.find(S)==c.end()||c.find(T)==c.end()) cout<<-1<<endl;
else
{
int v1=c[S],v2=c[T];
if(g[v1][v2]>=INF) cout<<-1<<endl;
else cout<<g[v1][v2]<<endl;
}
}
return 0;
}
收获:
1.了解了Floyd算法的原理,其中用到了动态规划的思路。
2.巩固了map的用法:
①声明一个map:map<string,int> c;(其中第一个是键值,第二个是对应的值)
②map的查找:c.find(string str);(如果找到返回元素的迭代器,找不到返回c.end())
③map的插入:c.insert(make_pair(string str,int value));(插入元素,它的键值为str,值为value)
④根据键值获得其对应的值:v=c[str];