图论初步<蒟蒻专属文章>

前言:    图论乃noip之重要知识点,但有点难理解 本人所以吃过很多亏node

     由于本人实在太弱,因此此篇乃正宗<蒟蒻专属文章>数组

正文:(本文仅介绍图论中的重点、难点,其他部分略将或不讲)

   

       图通常来讲有二种存储方法:邻接矩阵和邻接表函数

邻接矩阵spa

      存储:拿二维数组来存
  
code

for(int i=1;i<=n;++i){   //f[q][z]表示点q与点z有没有边相链接
    cin>>q>>z;  //noip基本别期望,最多三四十分
    f[q][z]=1;  //无向边要存双向 
    f[z][q]=1;
} 

       但是,虽然存储简单,可效率也过低了(尤为是些超级稀疏的矩阵)blog

  并且,坏处还没完:读取效率也很低!ip

       读取:ci

  

cin>>x;//读入x,查与x有关的点 
for(int i=1;i<=n;++i){  //听说++i比i++快一些 
    if(f[x][i]==1){
        cout<<i<<" ";
    } 
} 

 这么暴力的for循环,不超时才怪呢get

  因此,另外一种办法来了:邻接表!!博客

 原理:

     通过链表的形式,高效的存储/读取边

先使用struct:(我太蒻,只会用struct存)

struct node{
           int u,v,next;//u起点,v终点,next待会在说 啥意思 
   }e[MAXN*2]; //无向图要*2(缘由:要存两次)!!!!有向图彷佛只要一倍 
   //这类数组名都用e,养成好习惯 

 

读取:

for(int i=1;i<=n;++i){
       cin>>q>>z;  //这类函数名名都用e,养成好习惯 
       add(q,z);  //无向边要存双向 
       add(z,q);  //一般 用自定义函数实现 
   }

add(加边函数):    注意:要定义head数组,表示点i当前的第一个链接的数组下标!!!!!

 

代码:

void add(int x,int y,){
   ++tot;
   e[tot].u=x;
   e[tot].v=y;
   e[tot].next=head[x]; 
   head[x]=tot;
}

一些question&Answer&注意事项:

1:为何恰恰要插队?

Answer:由于若是不插队,将要加的边就无法指向上一个了(难道你还for一遍?);

2:链表结构其实还有不少其他的办法实现,但我写的这种更适合初学者

(emm.....好像就两个也)

 “遍历”方式:

cin>>a; //问和a号点相邻的边有哪些
    for(int i=head[a];i!=0;i=e[i].next){  //从点a的第一条边开始,若为0结束 
        cout<<e[i].u<<" "<<e[i].v<<endl;   // 到下一个数组下标 
    } 

(完)

写在后面的话:

     这是个人第一篇博客(bug必定不少

  本人的我的主页(洛谷)https://www.luogu.com.cn/user/236929  

    本人的我的主页https://www.cnblogs.com/Craker/

欢迎来访!

谢谢!

本人QQ:2783119105

本人邮箱:yixuazeng66@126.com

若有问题,请在评论区指出或私信我,

谢谢!

相关文章
相关标签/搜索