那HDU的2544作为复习最短路的题目,用不同算法。
迪杰斯特拉
有点像普利姆算法的精简版,不能有负权边
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 99999
#define qmin(a,b) a > b ? b : a
//最短路
//迪杰斯特拉
int G[200][200];
int vis[200];
int djs (int n,int s)
{
int d[200];
memset(vis,0,sizeof(vis));
int i,k;
for (i = 1;i <= n;i++)
d[i] = G[1][i];
d[1] = 0;
vis[1] = 1;
int imin,xb = 1;
for (i = 1;i < n;i++)
{
imin = MAX;
for (k = 1;k <= n;k++) //以xb为起点↓
if (!vis[k] && d[xb] + G[xb][k] < d[k]) //最短的那条边,快到碗里来
d[k] = d[xb] + G[xb][k];
vis[xb] = 1;
for (k = 1;k <= n;k++)
if (!vis[k] && imin > d[k])
imin = d[xb = k]; //找到最小的点,并以此为起点找最短
vis[xb] = 1;
}
return d[n];
}
int main()
{
int n,m;
while (scanf ("%d%d",&n,&m),n || m)
{
int i,k;
for (i = 0;i <= n;i++)
for (k = 0;k <= n;k++)
if (i == k)
G[i][k] = 0;
else
G[i][k] = MAX;
for (i = 0;i < m;i++)
{
int a,b,c;
scanf ("%d%d%d",&a,&b,&c);
if (c < G[a][b])
{
G[a][b] = c;
G[b][a] = c;
}
}
int ans = djs(n,1);
printf ("%d\n",ans);
}
return 0;
}
贝尔曼福特
可以有负权边,就是不停的松弛,时间复杂度有点高
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 99999
#define qmin(a,b) a > b ? b : a
//最短路
//贝尔曼福特
struct E
{
int e,v;
int w;
}e[10000];
int cont;
int BF (int n,int s)
{
int d[200];
int i,k;
for (i = 0;i <= n;i++)
d[i] = MAX;
d[s] = 0;
for (i = 1;i < n;i++) //找n - 1条边
{
for (k = 0;k < cont;k++) //把每条边都遍历一遍
{
int a = e[k].e,b = e[k].v;
d[b] = qmin (d[b],d[a] + e[k].w); //松弛
}
}
return d[n];
}
int main()
{
int n,m;
while (scanf ("%d%d",&n,&m),n || m)
{
int i,k;
cont = 0;
for (i = 0;i < m;i++)
{
int a,b,c;
int tf = 1;
scanf ("%d%d%d",&a,&b,&c);
for (k = 0;k < cont;k++)
if ((e[k].e == a && e[k].v == b) || (e[k].e == b && e[k].v == a))
if (e[k].w > c)
{
e[k].w = c;
tf = 0;
break;
}
if (tf)
{
//无向图
e[cont].e = a;
e[cont].v = b;
e[cont++].w = c;
e[cont].e = b;
e[cont].v = a;
e[cont++].w=c;
}
}
int ans = BF(n,1);
printf ("%d\n",ans);
}
return 0;
}
弗洛伊德
这简直就像暴力啊,时间复杂度大的夸张,但是求出了每两个点之间的最短路,对于数据多而且图小的题目还是可以考虑的。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 99999
#define qmin(a,b) a > b ? b : a
//最短路
//弗洛伊德
int G[200][200];
int fld (int n,int s)
{
int d[200][200];
int i,j,k;
memcpy(d,G,sizeof (G));
for (i = 0;i <= n;i++)
for (k = 0;k <= n;k++)
for (j = 0;j <= n;j++)
d[k][j] = qmin (d[k][j],d[k][i] + d[i][j]);
return d[s][n];
}
int main()
{
int n,m;
while (scanf ("%d%d",&n,&m),n || m)
{
int i,k;
//邻接矩阵初始化
for (i = 0;i <= n;i++)
for (k = 0;k <= n;k++)
if (i == k)
G[i][k] = 0;
else
G[i][k] = MAX;
for (i = 0;i < m;i++)
{
int a,b,c;
scanf ("%d%d%d",&a,&b,&c);
if (G[a][b] > c)
{
G[a][b] = c;
G[b][a] = c;
}
}
int ans = fld(n,1);
printf ("%d\n",ans);
}
return 0;
}
SPFA
BF的队列优化,有点像BFS。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 99999
#define qmin(a,b) a > b ? b : a
//最短路
//SPFA
struct node
{
int v;
int w;
struct node *next;
}head[10001];
int q[1000000]; //队列
int s = 0,e = 0;
int SPFA (int n,int st)
{
bool inq[200]; //标记是否还在队列中(队列中的不在入队列)
int d[200];
int i;
memset (inq,0,sizeof (inq));
for (i = 0;i <= n;i++)
d[i] = MAX;
s = 0;
e = 0;
d[st] = 0;
q[s++] = st;
inq[st] = 1; //源点入队列并标记
while (s > e)
{
int now = q[e++];
inq[now] = 0; //出队列的就恢复标记
struct node *p = head[now].next;
while (p != NULL)
{
if(d[p->v] > d[now] + p->w) //松弛成功
{
d[p->v] = d[now] + p->w;
if (!inq[p->v]) //如果在队列中就不入队列
{
q[s++] = p->v;
inq[p->v] = 1;
}
}
p = p->next;
}
}
return d[n]; //其他的和BF一样了
}
int add (int a,int b,int c) //邻接链表
{
struct node *t = new node;
t->v = b;
t->w = c;
t->next = NULL;
struct node *p = &head[a];
while (p->next != NULL)
p = p->next;
p->next = t;
return 1;
}
int main()
{
int n,m;
while (scanf ("%d%d",&n,&m),n || m)
{
memset(head,0,sizeof (head));
int i,k;
for (i = 0;i < m;i++)
{
int a,b,c;
int tf = 1;
scanf ("%d%d%d",&a,&b,&c);
add (a,b,c);
add (b,a,c);
}
int ans = SPFA(n,1);
printf ("%d\n",ans);
}
return 0;
}
SPFA前向星版本
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#define EGMAX 200000
#define DOMAX 2000
#define MAX 999999
using namespace std;
struct node
{
int e;
int w;
int next;
}eg[EGMAX];
int head[DOMAX];
int cont;
void add(int s,int e,int w)
{
eg[cont].e = e;
eg[cont].w = w;
eg[cont].next = head[s];
head[s] = cont++;
}
int dis[DOMAX];
bool vis[DOMAX];
int SPFA(int s,int e,int n)
{
int now;
queue<int> que;
memset(vis,0,sizeof (vis));
for (int i = 0;i <= n;i++)
dis[i] = MAX;
vis[s] = 1;
dis[s] = 0;
que.push(s);
while (!que.empty())
{
now = que.front();
que.pop();
vis[now] = 0;
for (int i = head[now];~i;i = eg[i].next)
{
if (dis[eg[i].e] > dis[now] + eg[i].w)
{
dis[eg[i].e] = dis[now] + eg[i].w;
if (!vis[eg[i].e])
{
vis[eg[i].e] = 1;
que.push(eg[i].e);
}
}
}
}
return dis[e];
}
int main()
{
int n,m;
while (~scanf ("%d%d",&n,&m) && (n || m))
{
cont = 0;
memset(head,-1,sizeof (head));
for(int i = 0;i < m;i++)
{
int s,e,w;
scanf ("%d%d%d",&s,&e,&w);
add(s,e,w);
add(e,s,w);
}
int ans = SPFA(1,n,n);
printf ("%d\n",ans);
}
return 0;
}
http://blog.csdn.net/codehypo