Dijkstra:
HDU2066:
题意:每组的第一行是三个整数T,S和D,表示有T条路,和草儿家相邻的城市的有S个,草儿想去的地方有D个;
接着有T行,每行有三个整数a,b,time,表示a,b城市之间的车程是time小时;(1=<(a,b)<=1000;a,b 之间可能有多条路)
接着的第T+1行有S个数,表示和草儿家相连的城市;
接着的第T+2行有D个数,表示草儿想去地方。
输出草儿能去某个喜欢的城市的最短时间。
6 2 3
1 3 5
1 4 7
2 8 12
3 8 4
4 9 12
9 10 2
1 2
8 9 10
9
#include<iostream>
using namespace std;
const int maxn = 1000 + 10;
const int INF = 0x3fffffff;
int map[maxn][maxn];
int T;
int S;
int D;
int dis[maxn];
bool used[maxn];
void init()
{
memset(used,0,sizeof(used));
int i;
int j;
for(i=0; i<maxn; i++) //初始化map都为无穷
{
dis[i] = INF;
for(j=0; j<maxn; j++)
{
map[i][j] = INF;
}
}
}
void dijkstra(){
dis[0] = 0;
int i;
for(i=0; i<maxn; i++){
int j;
int min = INF;
int min_j = -1;
for(j=0; j<maxn; j++){ //找出当前最优的点
if(!used[j] && min > dis[j]){
min = dis[j];
min_j = j;
}
}
if(min_j == -1){ //不存在最优点时结束
return ;
}
used[min_j] = true; //将最优点标志为用过
for(j=0; j<maxn; j++){
if(!used[j] && dis[j] > dis[min_j] + map[min_j][j]) { //没有访问过并且当初值比之前对应的dis值要小,就更新该值
dis[j] = dis[min_j] + map[min_j][j];
}
}
}
}
int main()
{
while(cin>>T>>S>>D)
{
init();
int i;
for(i=0; i<T; i++)
{
int a;
int b;
int values;
cin>>a>>b>>values;
if(map[a][b] > values) //无向时为map[a][b] = map[b][a];有向时分别输入map[a][b],map[b][a]
{
map[a][b] = map[b][a] = values;
}
}
for(i=0; i<S; i++) //开始的城市的值为0
{
int begin;
cin>>begin;
map[0][begin] = 0;
map[begin][0] = 0;
}
dijkstra();
int mincost = INF;
for(i=0; i<D; i++) //找出想去中的最优路径
{
int ans;
cin>>ans;
if(mincost > dis[ans])
{
mincost = dis[ans];
}
}
cout<<mincost<<endl;
}
return 0;
}
SPFA:
思路:不是枚举所有节点,而是通过队列来进行优化 设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止
int SAFP(int start,int n){
queue<int>Q;
dis[0] = 0;
vist[start] = true;
Q.push (start); //将初始点压入队列
while(!Q.empty()){
int t;
t = Q.front ();
Q.pop ();
for(int i=1; i<=n; i++){
if(dis[t] + map[t][i] < dis[i]){
dis[i]=dis[t] + map[t][i];
if(!vist[i]){
vist[i]=true;
Q.push (i);
cnt[i]++;
}
}
}
vist[t]=false;
if(cnt[t]>=n) //有环时结束循环
return -1;
}
}
Floyd:
void floyd(){ //时间复杂度为o(n * n * n),推导过程还不明白
for(int k=1; k<=n; k++){
for(int i=1; i<=n; i++){
for(int j=1; j<=n; j++){
if(map[i][j] > map[i][k] + map[k][j]){
map[i][j] = map[i][k] + ?map[k][j];
}
}
}
}
}