最近在看图论的经典算法,
先看的是求单源最短路的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菜鸟感觉很好~
uva 247 Calling Circles(Floyd 的简单应用)
原文地址:http://blog.csdn.net/u013382399/article/details/38944229