1. SPFA(Shortest Path Faster Algorithm)
1994年,西南交通大学的段凡丁发表了SPFA,SPFA在Bellman-Ford算法的基础上加上一个队列优化,减少了冗余的松弛操作。
关于最短路径的SPFA快速算法(段凡丁):http://www.cnki.com.cn/Article/CJFDTotal-XNJT402.015.htm
wiki:https://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct Node
{
int v,w;
Node *next;
Node(int x,int y):v(x),w(y),next(0){}
};
struct Graph
{
int VNum,ENum;
vector<Node *> Adj;
};
void createGraph(Graph &G)
{
cin>>G.VNum>>G.ENum;
for(int i=0;i<G.VNum;++i)G.Adj.push_back(0);
for(int i=0;i<G.ENum;++i)
{
int u,v,w;
cin>>u>>v>>w;
Node *p=new Node(v,w);
p->next=G.Adj[u];
G.Adj[u]=p;
}
}
vector<int> SPFA(Graph G,int s)
{
vector<int> d(G.VNum,INT_MAX);
vector<bool> flag(G.VNum,false);
d[s]=0;
queue<int> Q;
Q.push(s);
flag[s]=true;
while(!Q.empty())
{
int u=Q.front();
Q.pop();
flag[u]=false;
for(Node *p=G.Adj[u];p;p=p->next)
{
int v=p->v,w=p->w;
if(d[u]+w<d[v])
{
d[v]=d[u]+w;
if(!flag[v])
{
Q.push(v);
flag[v]=true;
}
}
}
}
return d;
}
//输入
//5 10
//0 1 10
//0 3 5
//1 2 1
//1 3 2
//2 4 4
//3 1 3
//3 2 9
//3 4 2
//4 0 7
//4 2 6
//
//输出
//0 8 9 5 7
int main()
{
Graph G;
createGraph(G);
int s=0;
vector<int> d=SPFA(G,s);
for(int i=0;i<d.size();++i)cout<<d[i]<<' ';
cout<<endl;
return 0;
}
2. 图的最长路径
(1)Bellman-Ford算法、Floyd-Warshall算法:将图中边的权重变为原来的相反数
(2)DAG(Directed Acyclic Graph,有向无环图):拓扑排序+动态规划
AOV(Activity On Vertex)网
AOE(Activity On Edge)网的关键路径
e(i) 表示活动 ai 的最早开始时间, l(i) 表示活动 ai 的最晚开始时间。
ve(i) 表示事件 vi 的最早发生时间, vl(i) 表示事件 vi 的最晚发生时间。
#include<iostream>
#include<vector>
#include<stack>
using namespace std;
struct Node
{
int v,w;
Node *next;
Node(int x,int y):v(x),w(y),next(0){}
};
struct Graph
{
int VNum,ENum;
vector<Node *> Adj;
};
void createGraph(Graph &G)
{
cin>>G.VNum>>G.ENum;
for(int i=0;i<G.VNum;++i)G.Adj.push_back(0);
for(int i=0;i<G.ENum;++i)
{
int u,v,w;
cin>>u>>v>>w;
Node *p=new Node(v,w);
p->next=G.Adj[u];
G.Adj[u]=p;
}
}
vector<int> GetInDegree(Graph G)
{
vector<int> indegree(G.VNum,0);
for(int u=0;u<G.VNum;++u)
{
for(Node *p=G.Adj[u];p;p=p->next)
{
int v=p->v;
++indegree[v];
}
}
return indegree;
}
void TopoSort(Graph G,stack<int> &T,vector<int> &ve)
{
vector<int> indegree=GetInDegree(G);
stack<int> S;
for(int u=0;u<G.VNum;++u)
{
if(indegree[u]==0)S.push(u);
}
while(!S.empty())
{
int u=S.top();
S.pop();
T.push(u);
for(Node *p=G.Adj[u];p;p=p->next)
{
int v=p->v,w=p->w;
if(--indegree[v]==0)S.push(v);
if(ve[u]+w>ve[v])ve[v]=ve[u]+w;
}
}
}
void CriticalPath(Graph G)
{
stack<int> T;
vector<int> ve(G.VNum,0);
TopoSort(G,T,ve);
vector<int> vl(G.VNum,ve[G.VNum-1]);
while(!T.empty())
{
int u=T.top();
T.pop();
for(Node *p=G.Adj[u];p;p=p->next)
{
int v=p->v,w=p->w;
if(vl[v]-w<vl[u])vl[u]=vl[v]-w;
}
}
for(int u=0;u<G.VNum;++u)
{
for(Node *p=G.Adj[u];p;p=p->next)
{
int v=p->v,w=p->w;
int ee=ve[u];
int el=vl[v]-w;
char tag=(ee==el)?'*':' ';
cout<<u<<"->"<<v<<' '<<w<<' '<<ee<<' '<<el<<' '<<tag<<endl;
}
}
}
//6 8
//0 1 3
//0 2 2
//1 3 2
//1 4 3
//2 3 4
//2 5 3
//3 5 2
//4 5 1
int main()
{
Graph G;
createGraph(G);
CriticalPath(G);
return 0;
}