关闭

图论模板

1151人阅读 评论(0) 收藏 举报
分类:

                                                       Dijkstra普通版实现

const int INF = ~0U >> 2;   //代表无穷大
const int VN = 100;        //最大顶点数
void Dijkstra(int s,int n)//s代表起点,n代表顶点个数
{
    bool vst[VN];
    memset(vst,0,sizeof(vst));
    for(int i = 1;i <= n;++i) d[i] = (i==s?0:INF);
    int kase = n; 
    while(kase--)
    {
        int x,m = INF;
        for(int y = 1;y <= n;++y) 
          if(!vst[y]&&d[y] <= m) m = d[x=y];
        vst[x] = 1;
        for(int y = 1;y <= n;++y)
        {
            if(d[y] > d[x]+w[x][y]) //松弛操作
            {
                d[y] = d[x] + w[x][y]; 
            }
        }
    }
}

 

除了求出最短路的长度外,使用Dijkstra算法也能很方便
地打印出从起点结点到所有结点的最短路,原理和动态规划中
的方案一样——从终点出发,不断顺着d[i]+w[i][j] = d[j]的边
(i,j)从结点j“退回”到结点i,直到回到起点。另外,仍然
可以用空间换时间,在更新d数组时维护“父亲指针”。
if(d[y] > d[x]+w[x][y])
{
    d[y] = d[x]+w[x][y];
    fa[y] = x;
}

                                                  Dijkstra优先队列加邻接表实现

#include <iostream>
#include <algorithm>
#include <queue>
#include <map>
#include <cstdio>
#include <cstring>
using namespace std;

typedef pair<int,int>pii;
const int INF = ~0U >> 2;
const int VN = 100;
int d[VN];
int top,w[2*VN],Head[VN],Key[2*VN],Next[2*VN];
void Add(int u,int v,int cost)
{
    w[top] = cost;
    Key[top] = v;
    Next[top] = Head[u];
    Head[u] = top++;
}
void Dijkstra(int s,int n)            //s代表起点,n代表顶点数
{
    priority_queue<pii,vector<pii>,greater<pii> > q;
    for(int i = 1;i <= n;++i) d[i] = (i==s?0:INF);
    q.push(make_pair(d[s],s));        //起点进入优先队列
    while(!q.empty())
    {
        pii u = q.top();
        q.pop();
        int x = u.second;   cout<<"x = "<<u.second<<" d = "<<d[x]<<endl;
        if(u.first != d[x])continue;  //已经算过,忽略
        for(int e = Head[x];e != -1;e = Next[e])
        {        
            int v = Key[e];
            if(d[v] > d[x] + w[e]){
               d[v] = d[x] + w[e];    //松弛成功,更新d[v]
               q.push(make_pair(d[v],v));//加入队列
            }
        }
    }
}
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        top = 0;
        memset(Head,-1,sizeof(Head));
        for(int i = 0;i != m;++i)
        {
            int x,y,cost;
            cin>>x>>y>>cost;
            Add(x,y,cost);
        }
        int s;
        cin>>s;
        Dijkstra(s,n);
        for(int i = 1;i <= n;++i)
           cout<<"i = "<<i<<" d = "<<d[i]<<endl;
        cout<<endl;
    }
    return 0;
}


 


 

解释一下上面的if(u.first != d[x])continue;这里也可以用一个标记数组来实现,但是要耗费一些内存,所以这里我就不用标记数组来判断该点是否实现过了。我解释一下为什么可以那样来判断呢?首先我们先想想,当有一个节点x已经更新过了压入队列.我们设当前再次遇到x节点的时候,我们此时记x为x'(x=x')则这次更新的d[x']一定比已经在队列里的小(d[x]>d[x']),所以此时x'(x=x')会再次压入队列。而x'(d[x'])先于之前x(d[x])已经在队列中的点先出队列。所以,之前在队列里的那个x(d[x])就无需再出队列进行再次对其他结点松弛了。

表述的可能有点乱,那就直接实例分析吧:

1 3 1

1 2 3

3 2 1

2 4 1

上面分别代表两个顶点和权值。

首先,我们设起点为1,则我们先把2,3压入队列,(此时d[2] = 3,d[3] = 1),所以下一次更新的是3这个节点,这时对2节点进行松弛操作将更新2节点即d[2] = 2,这时在将其压入队列,此时队列中就会存在两个2节点了,而我们在用2节点对其他点进行松弛的时候,只要用最短的一个就好了(即,d[2]=2)。ok,解释完毕。不知道你懂了没有。

 

5
1
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

图论常用模板

该模板基于刘汝佳算法竞赛入门经典--训练指南 该模板部分参考自《ACM国际大学生程序设计竞赛--算法与实现》 图论常用模板 转载请注明:转自http://blog.csdn.net/...
  • a15129395718
  • a15129395718
  • 2016-09-07 20:13
  • 733

图论:求割顶和块

/先通过一道题目: 存在n个通讯站,它们之间可以相互通讯(直接或间接),若其中的一个通讯站损坏,那么是否会影响正常工作? 可以将这些通讯站分成几个子站,使得每个子站内部只损坏一个通讯站时还可以正常...
  • yumao19921006
  • yumao19921006
  • 2013-03-02 13:31
  • 930

ACM模板 图论

acm图论模板
  • gdymind
  • gdymind
  • 2017-01-05 20:54
  • 195

图论模板小汇总

图论模板小汇总
  • Monster__Yi
  • Monster__Yi
  • 2016-07-17 20:56
  • 516

图论中的常见算法分析比较和模板

图论小结(一)     从一开始搞ACM到现在也有几个年头了,而搞图论的时间可是从一开始搞ACM开始。所以,总是对图论有着一种独有的感情。图论的内容说难不难,但是确实在算法中日常生活中可以经...
  • u010016150
  • u010016150
  • 2014-02-19 16:46
  • 2167

ACM-图论-拓扑排序

拓扑排序用于解决图论中有向图的一类序列问题。即在某一个有向图graph中,假设每一条有向边(u,v)代表节点u必须排在节点v的前面,那么按照这样的规则,将所有的节点进行排序,最终得出的序列就称为拓扑序...
  • u011787119
  • u011787119
  • 2015-08-03 16:10
  • 1378

【模板】其他图论

LCA(暴力):#include #include #include #include using namespace std; const int MAXN = 50000 + 50; in...
  • Loi_Meiko
  • Loi_Meiko
  • 2016-11-16 16:45
  • 256

图论各种概念总结,

匹配: 给定一个二分图,在G的一个子图G’中,如果G’的边集中的任意两条边都不依附于同一个顶点,则称G’的边集为G的一个匹配 最大匹配: 在所有的匹配中,边数最多的那个匹配就是二分图的最大匹配了...
  • u013514625
  • u013514625
  • 2014-03-07 23:42
  • 1122

数据结构:图论基础

图概述 图(Graph)是一种比线性结构和树形结构都要复杂的数据结构。简单讲,图是由表示数据元素的的集合V和表示数据之间关系的集合E组成。其中,数据元素常称作顶点(vertex),数据之间的关系...
  • lanmolei814
  • lanmolei814
  • 2014-11-12 22:21
  • 1211

基本图论算法--《算法导论》

广度优先搜索(BFS)算法描述对于一个给定的图G(V,E)G (V,E) 和一个源节点SS BFS能遍历所有从SS出发能到达的节点,并计算SS 能到达每一个节点的距离(最少的边数),并生成一可广度优先...
  • Dylan_Frank
  • Dylan_Frank
  • 2016-08-23 16:58
  • 733
    个人资料
    • 访问:262787次
    • 积分:5966
    • 等级:
    • 排名:第4963名
    • 原创:290篇
    • 转载:10篇
    • 译文:4篇
    • 评论:36条
    研究生生涯专栏
      深入理解计算机系统