月球美容计划之最短路
2014-05-31 21:07
204 查看
那HDU的2544作为复习最短路的题目,用不同算法。
迪杰斯特拉
有点像普利姆算法的精简版,不能有负权边
贝尔曼福特
可以有负权边,就是不停的松弛,时间复杂度有点高
弗洛伊德
这简直就像暴力啊,时间复杂度大的夸张,但是求出了每两个点之间的最短路,对于数据多而且图小的题目还是可以考虑的。
SPFA
BF的队列优化,有点像BFS。
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
迪杰斯特拉
有点像普利姆算法的精简版,不能有负权边
#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
相关文章推荐
- 月球美容计划之最短路
- 月球美容计划之最短路
- 月球美容计划之最小生成树(MST)
- 月球美容计划之最小生成树(MST)
- 月球美容计划之维尼的背包(基础篇)
- 月球美容计划之并查集
- 月球美容计划之图的储存结构汇总
- 月球美容计划之图的储存结构汇总
- 月球美容计划之那些天我们学过的KMP
- ACM 2. 旅行计划(水最短路)
- POJ训练计划2253_Frogger(最短路/floyd)
- SDUT 3363 数据结构实验之图论七:驴友计划(最短路)
- 队爷的讲学计划 (强连通缩点+最短路)
- TOJ 2732存钱计划(三)(单源最短路)
- 我国月球登陆计划落月工程已经启动
- 谭松松的旅游计划 【LCA 求最短路】
- SDUT 3363-数据结构实验之图论七:驴友计划(最短路_dijkstra)
- 数据结构实验之图论七:驴友计划 最短路中最小花费
- BZOJ2595 [Wc2008]游览计划 【状压dp + 最短路】
- 【 题集 】 寒假计划——最短路