最近在看图论的经典算法,
先看的是求单源最短路的dijkstra,优化后的算法用了优先队列,看起来有点复杂。
感觉 弗洛伊德(Floyd) 要比 迪克斯特拉(dijkstra) 更好理解一点,但是Floyd是三层循环,当然会慢很多。一旦数据开大就跪了吧。
floyd可以用来求 两个 连通点间的最短路问题。同时可以得到边权的和,即最短路的长度。
另外一个比较简单的应用,还可以用来判断两点间的连通性。即判断两点是否连通。本题就是弗洛伊德的这种简单用法。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#include<string>
#include<algorithm>
using namespace std;
#define mem(a) memset(a,0,sizeof(a))
int n,m;
string s1,s2,str[30];
map<string,int> ma;
int g[30][30];
int vis[30];
void init()
{
mem(g);
s1.clear();s2.clear();
for(int i=0;i<30;i++)
str[i].clear();
ma.clear();
}
void floyd()
{
for(int k=0;k<n;k++){
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
g[i][j]=g[i][j]||(g[i][k]&&g[k][j]);
}
}
}
}
int main()
{
// freopen("out.txt","w",stdout);
int kase=0;
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
int t=0;
init();
for(int i=0;i<m;i++)
{
cin>>s1>>s2;
int id1,id2;
if(ma.count(s1)){
id1=ma[s1];
}
else{
id1=t;
str[t]=s1;
ma[s1]=t++;
}
if(ma.count(s2)){
id2=ma[s2];
}
else{
id2=t;
str[t]=s2;
ma[s2]=t++;
}
g[id1][id2]=1;
}
floyd();
if(kase) printf("\n");
kase++;
printf("Calling circles for data set %d:\n",kase);
mem(vis);
for(int i=0;i<n;i++)
if(!vis[i])
{
cout<<str[i];
for(int j=i+1;j<n;j++){
if(!vis[j]){
if(g[i][j]&&g[j][i]){
cout<<", "<<str[j];
vis[j]=1;
}
}
}
cout<<endl;
}
}
return 0;
}
本题需要对数据加以处理:
实际问题给的是两个人的名字,表示两者之间的关系。但是在使用Floyd算法的时候,“名字”并没有办法直接使用。
所以想到用string数组把每个名字先保存下来,通过其下标来对该名字进行操作。
另外用到了map来判断此名字在之前有没有出现过,从而扩展 名字数组 。
1y菜鸟感觉很好~