標籤:blog http 資料 2014 art 演算法
那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//最短路//SPFAstruct 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;}
http://blog.csdn.net/codehypo