您的位置:首页 > 其它

月球美容计划之最短路

2014-05-31 21:07 204 查看
那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
;
}

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
;
}

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]
;
}

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
;          //其他的和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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: