图论基础——邻接链表存图+拓扑排序

Posted jhl0824

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论基础——邻接链表存图+拓扑排序相关的知识,希望对你有一定的参考价值。

邻接链表存图,在这里其实是用数组进行模拟

又叫做链式存储法,本来是要用链表实现的,但大多数情况下只需要用数组模拟即可

例:

u(边的起点) v(边的终点) w(边的权值)
4 2 1
1 2 3
1 4 1
1 5 2
4 3 4
2 3 1

 

 

 

技术图片

话不多说,直接上代码

for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u1,&v1,&w1);
        e[i].u =u1;//赋给第i条边的起点        
        e[i].v =v1;//赋给第i条边的终点
        e[i].w =w1;//赋给第i条边的权值
        e[i].next =head[u1];//现在这条边的上一条边=现在这条边的起点的上一条边(u1是起点) 
   head[u1]=i;//于是,对于以后的边来说,现在这条边就是起点的上一条边 }

注:e[i]为一个结构体,负责记录每一条边的信息

struct Node{
    int u;//边的起点
        int v;//边的终点
        int w;//边的权值
    int next;//边的上一条边(用于连接)
}e[边的最大条数];    

总的来说,这是一种存图的方法,更是图论的基础

 

拓扑排序

 拓扑排序是对有向无环图(Directed Acyclic Graph简称DAG)求出一个顶点序列,使其满足:对于任意边(u,v)?E,u在序列的位置总在v之前。 

   拓扑排序实现方法如下:
  (1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.//入度:到这个点的边有多少条
  (2)从图中删去该顶点,并且删去从该顶点发出的全部有向边,并且更新点的入度.
  (3)重复上述两步,直到剩余的图中不再存在没有前趋的顶点为止.
 
 使用方法:1、邻接矩阵+直接法。(空间开销大,不能判断有环)
                   2、邻接链表+栈(空间小,可以判断环)
 所以,一般用来实现
bool topsort()//拓扑排序,有拓扑序返回真,否则返回假 
{
    int p,q;
    for(int i=1;i<=n;i++)//先找到入度为0的节点入栈 
    {
        if(!d[i])s.push(i);//d[i]表示i点的入度,在加边的时候初始化d[i]
    }
    while(!s.empty())//当栈非空进行操作 
    {
        p=s.top();//记录栈顶节点 
        s.pop();//弹出栈顶节点 
        ans[cnt++]=p;//将弹出节点存储到结果数组,并计数 
        for(int i=head[p];i!=-1;i=e[i].next)//清除该节点的出度 
        {
            q=e[i].v;
            if(!(--d[q]))s.push(q);//如果又发现入度为0的节点,继续入栈 
        }
    }
    if(cnt<=n)return false;//当有节点没入栈,则说明存在环 
    return true;
}

 

另外在需要最大和最小拓扑序时,就要用到优先队列来存入

代码主体差不多,只是优先队列定义与栈不同罢了

以上是关于图论基础——邻接链表存图+拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

邻接表存图

luogu_4017题解最大食物链计数(拓扑排序)

生化危机 邻接表存图+BFS

ACM模板——链式前向星&&邻接表存图

SDOI2010_大陆争霸(邻接表存图)

小航的算法日记图论