链式前向星

声明

 


 

 

   题目

    给你一个有 n 个点和 m 条边(允许有重边)的无向图及每条边的边权,求:和点 k 所有相连的边的终点和边权,以及相连的边数。(此题也可暴力枚举,但为了讲前向星,还是用了前向星来做)

 

  输入输出格式:

    输入格式:

      输入数据第一行两个数 n,m,意义如题目所示。

      接下来 m 行每行有 3 个用空格隔开的数,其中第 i 行的 3 个数 x[i],y[i],w[i] 分别表示第 i 条边的起点、终点和边权。

      最后一行仅一个数 k,表示要查询的点,查询内容如题所示。

    输出格式:

      共 t+1 行。

      前 t 行每行两个数,其中第 j 行的两个数分别代表第 j 条与 k 相连的边的终点和边权,之间用空格隔开。

      最后一行一个整数 s,表示与 k 点相连的边数。

      注意:输出的前 t 行的边的顺序可以打乱,即第 j 条边放在某一条边的前面或后面输出是同样的答案,但禁止重复输出(除非两条相同的边)!!!

  样例输入:  

    4  5
    1  4  3
    3  2  2
    1  2  1
    4  3  4
    1  4  2
    4  

  

  样例输出

    1  2
    3  4
    1  3
    3

 

  介绍:前向星用一维数组实现,是邻接矩阵(二维数组实现)的优化,大大节省了存储空间和查找时间,在图论和需建图解题的题目中发挥着极大的作用!!!(当然此题也可以用邻接矩阵做,但数据一旦超过 3000 ,甚至达到 一万  或 十万  甚至 百万千万  的话,邻接矩阵就完全无能为力了)

 

  了解之后,让我们来真正接触一下前向星吧!

 


  

      First:构建链式前向星~(也是核心步骤

 

              
 1 procedure add(x,y,z:longint);      //加一条从 x 到 y 的边权为 w 的边
 2 begin
 3        inc(tot);                              //此条边的编号
 4        next[tot]:=first[x];              // next 记录下一条边的编号(边的顺序 
 5                                                    无所谓)
 6        first[x]:=tot;                       // first 记录第一条边的编号(哪条边作 
 7                                                    为第一条边也无所谓)
 8        en[tot]:=y;                         // en 记录编号为 tot 的边的终点
 9        len[tot]:=z;                        // len 记录编号为 tot 的边的边权
10 end;
建链表函数

 

 

         
1 for i:=1 to m do              
2 begin
3         readln(x,y,w);  
4         add(x,y,w);          //调用函数建表(正向建一次) 
5         add(y,x,w);          //调用函数建表(反向建一次)
6 end;    
7 (因为是无向边,所以要正反建两次~)
主程序调用建表函数以完成建前向星过程

 


 

       Next:线性查询!!!      

            
now:=first[k];                           //找起点为 k 的第一条边的编号

while now<>0 do                      //当边的编号不为零即还有边未询问是进 
                                                  行线性查询
begin

    writeln(en[now],' ',len[now]);//找到一条边,就输出信息,因为可以乱 
                                                 序(若按字典序输出,则存进数组里排 
                                                 一下序就好啦~)

    now:=next[now];                //线性查询下一条边(查询操作中的精 
                                                髓!)

    inc(cnt);                            //累计边的个数

end;
查询过程

 


 

      Last:输出~

          其实你们应该早发现了,在线性查询的过程中以经输出过终点和边权了,且剩下要输出的边数 s 其实就是 t 即程序中的 cnt !!!(废话!这只要是个人都能看出来的好吗?!)
      于是 writeln(cnt); 就完美地结束了此题!!!

 


      

     以下是标程!!!

             
 1 var
 2         x,y,w,tot,i,n,k,now,e,m,cnt:longint;
 3         first,en,next,len:array[0..1000001] of longint;
 4 procedure add(x,y,w:longint);    //建表函数
 5 begin
 6         inc(tot);
 7         next[tot]:=first[x];
 8         first[x]:=tot;
 9         en[tot]:=y;
10         len[tot]:=w;
11 end;
12 begin
13         readln(n,m);
14         for i:=1 to m do               //调用函数建表
15         begin
16                 readln(x,y,w);
17                 add(x,y,w);
18                 add(y,x,w);
19         end;
20         readln(k);
21         now:=first[k];                //开始查询
22         while now<>0 do
23         begin
24                 writeln(en[now],' ',len[now]); //边询问边输出
25                 now:=next[now];
26                 inc(cnt);
27         end;
28         writeln(cnt);                   //最后输出边数此题完美结束
29 end.
标程

 


    

       学后推荐一个用到前向星的模板:最小生成树 Prim 算法

 

posted @ 2019-01-23 22:19  》落雨~·~情缘《  阅读(145)  评论(0编辑  收藏  举报