单源最短路径算法模板(Dijkstra+BellmanFrod)

//最短路径算法模板 //前面两个结构体共用 #include<queue> #include<vector> #include<cstring> #define maxn 99  //按最大节点数宏定义 #define INF 0xfffffff using namespace std; struct Edge  //节点结构体 {     int from;  //起始点     int to;   //终止点     int dist;   //起始点到终止点的距离 }; struct HeapNode  //队列节点结构体,用于入队 {     int d;   //该点到汇点的距离     int u;    //该点     bool operator <(const HeapNode& rhs) const     {         return d>rhs.d;   //优先队列,距离优先,距离值小的点在队头     } }; /*Dijkstra算法求最短路径 时间复杂度:O(ElogE) 步骤: 1、初始化距离数组 2、设置所有点为未访问过 3、找出所有未访问过得点中距离最小的点,标记其为访问过 4、对操作(3)中所找到的点的相邻的边进行松弛 5、重复操作(3)和(4)直到所有点都访问过 */ /*算法特点: 用于计算边权均为正的图的单源最短路径,若存在权为负的节点,则无法求解 */ struct Dijkstra {     int n,m;     vector<Edge> edges;  //点数和边数     vector<int> G[maxn];  //边列表,i边可连通到边G[i][j];     bool done[maxn];  //是否已永久标记     int d[maxn];   //s汇点到各点的距离     int p[maxn];   //最短路中的一条弧     void init(int n)   //析构函数,用完后“初始化”,便于下次使用     {         this->n=n;         for(int i=0;i<n;i++)G[i].clear();         edges.clear();     }     void AddEdge(int from,int to,int dist)  //构造函数,将值初“始化”为输入情况     {         edges.push_back((Edge){from,to,dist});         m=edges.size();         G[from].push_back(m-1);     }     void dijkstra(int s)//最短路径算法     {         priority_queue<HeapNode> Q;         for(int i=0;i<n;i++)d[i]=INF;//所有点到汇点的距离初始化为最大值         d[s]=0; //自身到自身的距离为0;         memset(done,0,sizeof(done)); //未处理任何定点,所有标记初始化为0         Q.push((HeapNode){0,s});         while(!Q.empty())         {             HeapNode x=Q.top();             Q.pop();             int u=x.u;             if(done[u])continue;             done[u]=true;             for(int i=0;i<G[u].size();i++)             {                 Edge& e=edges[G[u][i]];                 if(d[e.to]>d[u]+e.dist)                 {                     d[e.to]=d[u]+e.dist;                     p[e.to]=G[u][i];                     Q.push((HeapNode){d[e.to],e.to});                 }             }         }     } }; /*BellmanFrod算法求最短路径 时间复杂度:O(kE) 步骤: 1、初始化d数组,ds=0,di=INF 2、枚举每一条边,进行松弛操作 3、将操作(2)重复执行|v|-1次 4、枚举每一条边,看是否还能进行松弛操作,若能,说明原图存在负权环 */ /*算法特点: 可用于计算存在权为负的边的图中的单源最短路径(当最短路径存在时) */ struct BellmanFrod {     int n;     int m;     vector<Edge> edges;     vector<int>G[maxn];     bool inp[maxn];//点是否在队列中     double d[maxn];//s到各点的距离     int p[maxn]; //最短路上的一条弧     int cnt[maxn]; //进队次数     //如果某节点进队n次,可以判断存在负圈     void init(int n)     {         this->n=n;         for(int i=0;i<n;i++)G[i].clear();         edges.clear();     }     void AddEdge(int from,int to,double dist)     {         edges.push_back((Edge){from,to,dist});         m=edges.size();         G[from].push_back(m-1);     }     bool negtiveCycle()     {         queue<int> Q;         memset(inp,0,sizeof(inp));         memset(cnt,0,sizeof(cnt));         for(int i=0;i<n;i++)         {             d[i]=0;             inp[0]=true;             Q.push(i);         }         while(!Q.empty())         {             int u=Q.front();             Q.pop();             inp[u]=false;             for(int i=0;i<G[u].size();i++)             {                 Edge& e=edges[G[u][i]];                 if(d[e.to]>d[u]+e.dist)                 {                     d[e.to]=d[u]+e.dist;                     p[e.to]=G[u][i];                     if(!inp[e.to])                     {                         Q.push(e.to);                         inp[e.to]=true;                         if(++cnt[e.to]>n)return true;                     }                 }             }         }         return false;     } }; 

你可能感兴趣的:(C++,模板,最短路径,单源)