基础图论--存图

图论蛮好玩的呢  比起数论真是有趣多了

有空整理一下下

首先,图是个什么鬼东东呢

graph, 一堆点集,一堆边集,可以把各种事物抽象成点,事物之间的联系用边来表示,边上还可有权值,表示距离费用等

e.g. 把各个城市抽象成点,城市之间可以由高铁直达的称作有联系(边), 边上还可附加权值,俩城市间距离等

至于一些基本概念, 有向无向,是否成环,入度出度等就不多讲啦 基本概念理解就好

现在看看存图,看不同情况来选适合的存图方式

邻接矩阵---二维矩阵 a[ n ][ m ], 可用a[i][j]=1或0表示点i,j之间是否右边,缺点就是很占空间耶

邻接表---可以用链表呢(详见数据结构与算法,一些算法中提及的优化呵呵呵, 缺点就是修改查询麻烦

vector---归到邻接表啦,开个vector<ll>v[ N ], 点i,j有边,直接v[ i ].push_back(j)就好了 耶  操作也相对简单,某些题很适用

前向星---记录下每个起始点的第一条边,先按点同时按边遍历,需要排序, 详见代码

struct node
{
    int s, e, w;
}edge[MAXN];//边集
bool cmp(node a, node b)
{
    if(a.s==b.s && a.e==b.e) return a.w<b.w;
    if(a.s==b.s) return a.e<b.e;
    return a.s<b.s;
}
int head[MAXN]; //存起点为i的第一条边的位置
int main()
{
    int n, m;
    int i, j, k;
    while(cin>>m>>n) //m点  n条边
    {
        for(i=0; i<n; i++)
            cin>>edge[i].s>>edge[i].e>>edge[i].w;
        sort(edge, edge+n, cmp);  //排序以边的起点非递减序排

        memset(head, -1, sizeof(head));
        head[edge[0].s]=0;
        for(i=1; i<n; i++)
            if(edge[i].s!=edge[i-1].s) //存起点为i的第一条边的位置
            head[edge[i].s]=i;

        for(i=1; i<=m; i++) //遍历各点  输出以该点为起始点的所有边
        {
            for(k=head[i]; edge[k].s==i && k<n; k++)
                cout<<edge[k].s<<‘ ‘<<edge[k].e<<‘ ‘<<edge[k].w<<endl;
        }
    }
}

链式前向星---不需排序 ,很巧妙, 详见代码

//链式前向星
/*
edge[0].to = 2;     edge[0].next = -1;      head[1] = 0;
edge[1].to = 3;     edge[1].next = -1;      head[2] = 1;
edge[2].to = 4;     edge[2],next = -1;      head[3] = 2;
edge[3].to = 3;     edge[3].next = 0;       head[1] = 3;
edge[4].to = 1;     edge[4].next = -1;      head[4] = 4;
edge[5].to = 5;     edge[5].next = 3;       head[1] = 5;
edge[6].to = 5;     edge[6].next = 4;       head[4] = 6;
*/
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<string>
using namespace std;
const int INF=0x3f3f3f3f;
typedef pair<int, int> p;
typedef long long ll;
#define fi first
#define se second
#define MAXN 10000+5
#define NIL -1
struct node
{
    int next, to, w; //edge[i].to 存 第i条边 的终点 .next存与边i同起点的前一条边
}edge[MAXN];
int head[MAXN];//head[i] i为有边节点 head存该节点 边 的最大编号 存的是边
int cnt;
void add(int u,int v,int w)//起点 终点 权值
{
    edge[cnt].w=w;
    edge[cnt].to=v;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
int main()
{
    int n, m;
    int i, j, k;
    int u, v, w;
    while(~scanf("%d%d", &n, &m)&& n && m) //n节点个数 m输入次数 一个节点可能有多条边
    {
        memset(head, -1, sizeof(head));
        cnt=0;
        for(i=0; i<m; i++)
        {
            scanf("%d%d%d", &u, &v, &w);
            add(u, v, w);
        }
        for(u = 1; u<=n; u++)
           for(i=head[u]; ~i; i=edge[i].next)//逆序遍历 i为边
                 printf("(%d %d)--> %d\n", u, edge[i].to, edge[i].w);
    }
}

感觉用链式前向星比较顺手,看具体题目要求再选了

原文地址:https://www.cnblogs.com/op-z/p/10804068.html

时间: 2024-09-30 02:49:09

基础图论--存图的相关文章

整合:图论存图方法及三种重要做法分析(Kruskal Dijkstra Bellman-Ford)

一.最短生成路的2种存图方法(邻接矩阵和邻接表): 1)邻接矩阵(适合稠密图即边远远多于点): 1.时间复杂度一般在n^2: 2.可以解决重边情况:map[i][j] = min( map[i][j] , input); 3.初始化:a[i][j] = INF;  a[i][i] = 0; 4.邻接矩阵点的最大极限在3000左右 5.图示: 2)邻接表(适合疏密图即边数近似于点数): 1.时间复杂度一般在mlog(n): 2.数组实现邻接表: ①定义:每个节点i都有一个链表,里面保存着从i出发的

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

邻接链表存图,在这里其实是用数组进行模拟的 又叫做链式存储法,本来是要用链表实现的,但大多数情况下只需要用数组模拟即可 例: 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条边的

图论——三种存图方式

今年暑假入坑了ACM,可以说开始的很晚了.平时看到各位大佬们的博客都写的很是精彩了,也想通过写博客来督促一下自己,总结一下自己的每天所学和一些感受吧,希望能一直坚持下去,这条路注定不会好走,那就坦然去接受一场场爆零,从零开始慢慢积累吧.(刚开始入坑,写的内容可能会有很多很多的问题,希望大家多多指出,一起进步.) 本来是最近在准备学习网络流,但是发现,基础差到模板里建图就有些不会,于是先来学学习如果存图,大概有三种这样的方式: 一.邻接矩阵存图   顾名思义就是用矩阵来记录一个图,矩阵中第 i 行

从存图到最短路算法的图论总结

INTRODUCTION: 图论算法在计算机科学中扮演着很重要的角色,它提供了对很多问题都有效的一种简单而系统的建模方式.很多问题都可以转化为图论问题,然后用图论的基本算法加以解决.--百度百科 对于OI而言,图是指由若干给定的点及若干条连接两点的线(边)所构成的图形 借助图论知识,我们往往可以将一些复杂的问题转化到基础的图论算法上,进而使用已有算法解决全新问题 那么想如果想要运用图论,首先要从存图开始 前排感谢教我图论的周润喵老师,syc学长,就序老师 可是我还是没学会 一,存图 对于一个图而

基础图论总结

在此之前需要先学会基本数据结构,递归以及搜索.回溯 用了半个月的时间终于搞完了全部的基础图论...仅介绍到差分约束 图的定义自己百度= =这里直接开始说图的存储. 图的存储有N种写法,我所知道的有邻接矩阵.边表.邻接表.前向星.边集数组.十字链表.邻接多重表,这里只讨论较容易实现的3种也是最为普遍的3种:邻接矩阵,边表和邻接表. 先说说邻接矩阵吧. 邻接矩阵是一种图的直接的储存方式,对于稠密图来说,邻接矩阵的效率要高于邻接表以及边表,但是如其名,我们需要一个n*n的二维数组,所以其空间复杂度是很

基础图论算法导引

ACM中常用图论算法 1. 拓扑排序 -> 拓扑排序的原理及其实现 2. 最短路径算法 -> 最短路算法总结 差分约束系统 -> 差分约束 前k短路 -> 前K短路径问题 3. 最小生成树问题扩展 -> 最?小?生?成?树?问?题?的?拓?展  最优比率生成树 -> 最优比率生成树 最小k度限制生成树 -> IOI2004国家集训队论文,由汪汀所著(网盘内有) 或者刘汝佳的黑书内有 裸题 poj1639 题解 4. 二分图匹配 -> 二分图的最大匹配.完美匹

邻接表存图

邻接表也叫边表,也是OI中常用的存图方法之一,以后所有的图论算法 我都打算用这个写,具体也不难理解. 这种存图方式是用了N(点的个数)个链表将整个图串联起来,串联方式 便是那个first数组. 我们首先定义了一个结构体,结构体一共有三个参数,终点,权值,这个边 的下一条边. 具体操作:每当输入一条边的数据时,我们将这组数据送进加边函数(也可以 直接写在main函数中的for循环里)cnt是边数,是一个给每条边编号的工具 我们存一下第cnt条边的终点权值以及与cnt相关的下一条边,这个串联是通过

生化危机 邻接表存图+BFS

生化危机 发布时间: 2015年10月10日 18:05   时间限制: 1000ms   内存限制: 256M 描述 X博士想造福人类, 研发一种可以再生肢体的药物, 可是很不幸......研究失败了, 他在蜥蜴身上实验的时候, 蜥蜴发生了变异, 更糟糕的是, 蜥蜴逃出了生化实验室. 恐怖的事情发生了, 疫情以X博士所在的城市为中心向四周扩散开, 最终, 整个地球上的城市都被感染了.假设整个地球一共有N个城市, 这N个城市是连通的, 有N-1条通道把他们连接起来.病毒会以一座城市为中心,在一天

[转载] 几张非常有意义的JavaScript基础学习思维图

原文:http://www.w3cfuns.com/forum.php?mod=viewthread&tid=5598364&extra=page%3D1%26filter%3Ddigest%26digest%3D1%26digest%3D1 1.JavaScript 数组 2.JavaScript 函数基础 3.Javascript 运算符 4.JavaScript 流程控制 5.JavaScript 正则表达式 6.JavaScript 字符串函数 7.JavaScript 数据类型