1. Bellman-Ford算法
实现c/c++代码如下:
/**
Initialize-single-source(G,s):
for each vertex v in V:
v.d <- OO
v.p <- NIL
s.d <- 0
Relax(u,v):
if u.d + w(u,v) < v.d:
v.d <- u.d + w(u,v)
v.p <- u
Bellman-Ford(G,w,s):
Initialize-Single-Source(G,s):
for i <-1 to |V| -1:
for each edge(u,v) in E:
relax(u,v)
for each edge(u,v) in E:
if v.d > u.d + w(u,v):
return false
return true
**/
#include<stdio.h>
#include<iostream>
#include<vector>
#include<set>
using namespace std;
const int MAX = 0xffff;
struct vertex {
int d;
int p;
};
vertex points[101];
vector<int> vs[101];
set<int> se;
set<pair<int,int> >bian;
int dist[101][101];
void init(int s){
for(set<int>::iterator it=se.begin();it!=se.end();it++){
int te = *it;
points[te].d = MAX;
points[te].p = -1;
}
points[s].d = 0;
}
void relax(int u,int v){
if(points[v].d > points[u].d + dist[u][v] ){
points[v].d = points[u].d + dist[u][v];
points[v].p = u;
}
}
bool bellman_ford(int s){
init(s);
int len = se.size()-1;
while(len--){
for(set<pair<int,int> >::iterator it= bian.begin();it!=bian.end();it++){
pair<int,int> tp = *it;
relax(tp.first,tp.second);
}
}
for(set<pair<int,int> >::iterator it= bian.begin();it!=bian.end();it++){
pair<int,int> tp = *it;
if(points[tp.second].d > points[tp.first].d+dist[tp.first][tp.second]){
return false;
}
}
return true;
}
//author:GUET_diadestiny
int main(){
int n;//边数
cin>>n;
while(n--){
int a,b,val;
cin>>a>>b>>val;
dist[a][b] = val;
vs[a].push_back(b);
se.insert(a);
se.insert(b);
bian.insert(make_pair(a,b));
}
if(!bellman_ford(0)){
cout<<"存在负权环路"<<endl;
}
for(set<int>::iterator it=se.begin();it!=se.end();it++){
int te = *it;
cout<<te<<" "<<points[te].p <<" "<<points[te].d<<endl;
//输出从源点0到任意一点te的最短路径距离points[te].d;
}
return 0;
}
//输入有向图测试数据(边数,从i指向j的权值val):
//8
//0 1 6
//0 4 7
//1 4 8
//4 3 9
//4 2 -3
//1 3 -4
//1 2 -2
//3 2 7
2. 基于拓扑排序的有向无环图单源最短路径问题
/**
dag-shortest-paths(G,w,s):
topologically sort the vertices of G:
Initialize-Single-Source(G,s)
for each vertex u taken in topologically sorted order:
for each edge(u,v) in E:
relax(u,v)
**/
#include<iostream>
#include<vector>
#include<stdio.h>
#include<set>
#include <stdlib.h>
#define WHITE -1
#define GREY 0
#define BLACK 1
using namespace std;
struct Node{
int data;
struct Node * next;
};
struct vertex{
int color;
int parent;
int final_time;
int first_time;
int d;
};
const int MAX = 0xffff;
vector<int> vs[101];//存储边的邻接表
vertex points[101];
set<int> se;//记录所有顶点编号
int time = 0;
Node* headlink = NULL;
int dist[101][101];
void init(int s){
for(set<int>::iterator it=se.begin();it!=se.end();it++){
int te = *it;
points[te].d = MAX;
points[te].parent = -1;
}
points[s].d = 0;
}
void relax(int u,int v){
if(points[v].d > points[u].d + dist[u][v] ){
points[v].d = points[u].d + dist[u][v];
points[v].parent = u;
}
}
void head_insert(int t){
Node * tp = (Node*)malloc(sizeof(Node));
tp->data = t;
tp->next = headlink->next;
headlink->next = tp;
}
void print_link(){
Node *ph = headlink->next;
while(ph){
cout<<ph->data<<" ";
ph = ph->next;
}
cout<<endl;
}
void dfs_visit(int u,vertex& p){
time++;
p.first_time = time;
p.color = GREY;
for(int i=0;i<vs[u].size();i++){
int te = vs[u][i];
if(points[te].color == WHITE){
points[te].parent = u;
dfs_visit(te,points[te]);
}
}
p.color = BLACK;
time = time + 1;
p.final_time = time;
head_insert(u);
}
void topsort_dfs(){
set<int>::iterator it = se.begin();
for(it=se.begin();it!=se.end();it++){
points[*it].color = WHITE;
points[*it].parent = -1;
}
for(it=se.begin();it!=se.end();it++){
int t = *it;
if(points[t].color == WHITE){
dfs_visit(t,points[t]);
}
}
}
void dag_shortpath(){
topsort_dfs();
init(0);
Node *ph = headlink->next;
while(ph){
int data = ph->data;
for(int i=0;i<vs[data].size();i++){
relax(data,vs[data][i]);
}
ph = ph->next;
}
}
//author:GUET_diadestiny
int main()
{
headlink = (Node*)malloc(sizeof(Node));
headlink->next = NULL;
int n;//边数
cin>>n;
while(n--){
int a,b,val;
cin>>a>>b>>val;
dist[a][b] = val;
vs[a].push_back(b);
se.insert(a);
se.insert(b);
}
dag_shortpath();//基于topsort的有向无环图的单源最短路径问题(时间复杂度为O(V+E))
print_link(); //输出一个拓扑排序序列
for(set<int>::iterator it=se.begin();it!=se.end();it++){
int te = *it;
cout<<te<<" "<<points[te].parent <<" "<<points[te].d<<endl;
//输出从源点0到任意一点te的最短路径距离points[te].d;
}
return 0;
}
//输入有向图测试数据(边数,从i指向j的权值val):
//8
//0 1 6
//0 4 7
//1 4 8
//4 3 9
//4 2 -3
//1 3 -4
//1 2 -2
//3 2 7