Dijkstra算法-邻接矩阵形式
复杂度:N^2
/* * Dijkstra算法,邻接矩阵形式: * 复杂度为O(n^2),仅可处理非负权图 * cost: 任意两点边权(不相连边需赋值INF) * n: 图中点的总数(当前点从0开始编号) * lowcost:任意点到源点的最短路 * beg: 源点 */ const int MAXN=1010; #define typec int const typec INF=0x3f3f3f3f; bool vis[MAXN]; int pre[MAXN]; void Dijkstra(typec cost[][MAXN],typec lowcost[],int n,int beg) { for(int i=0;i<n;i++) { lowcost[i]=INF; vis[i]=false; pre[i]=-1; } lowcost[beg]=0; for(int j=0;j<n;j++) { int k=-1; int Min=INF; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[i]<Min) { Min=lowcost[i]; k=i; } if(k==-1)break; vis[k]=true; for(int i=0;i<n;i++) if(!vis[i]&&lowcost[k]+cost[k][i]<lowcost[i]) { lowcost[i]=lowcost[k]+cost[k][i]; pre[i]=k; } } }
Dijkstra算法-邻接表形式
复杂度:Elog(E)
/* * 优化Dijkstra,邻接表形式 * 复杂度O(ElogE),仅适合无负权图 * E[i]: 与i点相连的边的集合,初始化方式: E[i].clear() * n: 图中点的总数,(节点编号从1开始) * start: 源点 * dist: 各点到源点的最短路 * MAXN: 最大边数 */ const int INF=0x3f3f3f3f; const int MAXN=1000010; struct qnode { int v; int c; qnode(int _v=0,int _c=0):v(_v),c(_c){} bool operator <(const qnode &r)const { return c>r.c; } }; struct Edge { int v,cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge>E[MAXN]; bool vis[MAXN]; int dist[MAXN]; void Dijkstra(int start,int n)//点的编号从1开始 { memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++)dist[i]=INF; priority_queue<qnode>que; while(!que.empty())que.pop(); dist[start]=0; que.push(qnode(start,0)); qnode tmp; while(!que.empty()) { tmp=que.top(); que.pop(); int u=tmp.v; if(vis[u])continue; vis[u]=true; for(int i=0;i<E[u].size();i++) { int v=E[tmp.v][i].v; int cost=E[u][i].cost; if(!vis[v]&&dist[v]>dist[u]+cost) { dist[v]=dist[u]+cost; que.push(qnode(v,dist[v])); } } } } void addedge(int u,int v,int w) { E[u].push_back(Edge(v,w)); } //---------------------------------------------------------------
SPFA算法-邻接表形式
复杂度:kE
/* * SPFA,邻接表形式 * 复杂度O(kE)(复杂度不定,改成栈有时更快),可处理负权图 * E[i]: 与i点相连的边的集合,初始化方式: E[i].clear() * n: 图中点的总数,(节点编号从1开始) * start: 源点 * dist: 各点到源点的最短路 * MAXN: 最大点数 */ const int MAXN=1010; const int INF=0x3f3f3f3f; struct Edge { int v; int cost; Edge(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge>E[MAXN]; void addedge(int u,int v,int w) { E[u].push_back(Edge(v,w)); } bool vis[MAXN];//在队列标志 int cnt[MAXN];//每个点的入队列次数 int dist[MAXN]; bool SPFA(int start,int n) { memset(vis,false,sizeof(vis)); for(int i=1;i<=n;i++)dist[i]=INF; vis[start]=true; dist[start]=0; queue<int>que; while(!que.empty())que.pop(); que.push(start); memset(cnt,0,sizeof(cnt)); cnt[start]=1; while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=0;i<E[u].size();i++) { int v=E[u][i].v; if(dist[v]>dist[u]+E[u][i].cost) { dist[v]=dist[u]+E[u][i].cost; if(!vis[v]) { vis[v]=true; que.push(v); if(++cnt[v]>n)return false; //cnt[i]为入队列次数,用来判定是否存在负环回路 } } } } return true; }
Ford算法-邻接表形式
复杂度:NE
/* * bellman_ford算法,邻接表形式 * 复杂度O(VE),可处理负权图 * E: 边集,初始化方式: E.clear() * n: 图中点的总数,star * start: 源点 * dist: 各点到源点的最短路 * MAXN: 最大点数 * 可以判断是否存在负环回路。返回true,当且仅当图中不包含从源点可达的负权回路 */ const int INF=0x3f3f3f3f; const int MAXN=550; int dist[MAXN]; struct Edge { int u,v; int cost; Edge(int _u=0,int _v=0,int _cost=0):u(_u),v(_v),cost(_cost){} }; vector<Edge>E; bool bellman_ford(int start,int n)//点的编号从1开始 { for(int i=1;i<=n;i++)dist[i]=INF; dist[start]=0; for(int i=1;i<n;i++)//最多做n-1次 { bool flag=false; for(int j=0;j<E.size();j++) { int u=E[j].u; int v=E[j].v; int cost=E[j].cost; if(dist[v]>dist[u]+cost) { dist[v]=dist[u]+cost; flag=true; } } if(!flag)return true;//没有负环回路 } for(int j=0;j<E.size();j++) if(dist[E[j].v]>dist[E[j].u]+E[j].cost) return false;//有负环回路 return true;//没有负环回路 } void addedge(int u,int v,int w) {//加的是单向边,即u->v权值为w E.push_back(Edge(u,v,w)); }
Ford算法-求任意最短路
复杂度:N^3
//---O(n^3)的任意最短 for(int k = 0; k < n; k++) for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) if(cost[i][j]<cost[i][k]*cost[k][j]) cost[i][j]=cost[i][k]*cost[k][j]; //--------------------------------------------