Luke_Hatch0718

博客园 首页 联系 订阅 管理

在计算机中存储数据结构——图,通常有两种方法。

一、邻接矩阵

定义二位数组map[n][m],其中任意一个元素map[i][j]表示:由i出发到j的一条边。对于无权图,map[i][j]=1表示i到j有边, map[i][j]=0表示i到j无边;对于有权图来说,map[i][j]=x表示i到j有边权为x的边,map[i][j]= ∞。对于无向图,map[i][j]=map[j][i],相当于正反两条边,此时矩阵斜向对称。

在知道端点的情况下查边快,但费内存,适用于点少的稠密图,可以用于oi中的简单算法。

#include <cstdio>

#include <iostream>

#include <cstring>

using namespace std;

int u, v, w;

int map[1000][1000];//邻接矩阵定义

void addedge(int u, int v, int w)//邻接矩阵加边

{

    map[u][v] = w;

}

int n, m;//n为点数,m为边数

int main()

{

    memset(map, 0x3f3f3f3f,sizeof(map));

    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; i++)

    {

         scanf("%d%d%d", &u, &v, &w);

         addedge(u, v, w);

    }

    for (int i = 1; i <= n; i++)

    {

         for (int j = 1; j <= n; j++)

         {

             printf("%010d ", map[i][j]);

         }

         printf("\n");

    }

    return 0;

}

 

二、前向星与链式前向星

1)前向星(几乎无用的算法,只为了链式前向星做铺垫)

edge类型的结构体e[i]数组:用于记录边的节点和权重信息。

head[i]数组:用于标记以第i个节点为起点在e数组中第一次出现的位置。

struct edge

{

    int u;//边的起点

    int v;//边的终点

    int w;//边的权值

};

edge e[10000];//边,i无实际意义,可以理解为边的编

比如说我们有边:

1,2,3

3,4,5

2,3,4

4,5,6

假设为无向图,double一下:

1,2,3

2,1,3

 

3,4,5

4,3,5

 

2,3,4

3,2,4

 

4,5,6

5,4,6

然后用sort二级排序,先按u从小到大排序,u相同的情况下再按v从小到大排序

1,2,3

2,1,3

2,3,4

3,2,4

3,4,5

4,3,5

4,5,6

5,4,6

代码:

#include <cstdio>

#include <iostream>

#include<algorithm>

using namespace std;

struct edge

{

    int u;//边的起点

    int v;//边的终点

    int w;//边的权值

};

edge e[10000];//边,i无实际意义,可以理解为边的编号

int n, m;//n为点数,m为边数

int head[1000];//以第i个节点为源头,所指出所有边的第一条边的编号

bool cmp(edge a, edge b)

{

 

    if (a.u < b.u)

    {

         return true;

    }

    else if (a.u==b.u)

    {

         if (a.v < b.v)

         {

             return true;

         }

         else

         {

             return false;

         }

    }

    else

    {

         return false;

    }

}

int main()

{

    scanf("%d%d", &n, &m);

    for (int i = 1; i <= m; i++)

    {

         scanf("%d%d%d", &e[2 * i].u, &e[2 * i].v, &e[2 * i].w);

         e[2 * i].u = e[2 * i - 1].u;e[2 * i].v = e[2 * i - 1].v;e[2 * i].w = e[2 * i - 1].w;

    }

    sort(e + 1, e + 2 * m + 1, cmp);

    head[1] = 1;

    for (int i = 2; i <= n; i++)

    {

         if (e[i - 1].u != e[i].u) { head[e[i].u] = i; }

    }

    return 0;

}

2)链式前向星:懒得用前向星排序了,于是干脆不排了,弄个链表,快一点点,少了个nlogn。

struct edge

{

    int v;//边的终点

    int head;//连接同一个节点的上一条边的编号

    int w;//边的权值

};

edge e[10000];//i可以理解为边的编号

int head[1000];//以第i个节点为源头,按输入顺序,所指出所有边的最后一条边的编号

代码:

#include <cstdio>

#include <iostream>

#include<algorithm>

#include<cstring>

using namespace std;

struct edge

{

    int ve;//边的终点

    int next;//连接同一个节点的上一条边的编号

    int we;//边的权值

};

edge e[10000];//i可以理解为边的编号

int n, m;//n为点数,m为边数

int head[1000];//以第i个节点为源头,按输入顺序,所指出所有边的最后一条边的编号

int cnt;//计数器

void add(int u,int v,int w)//加边

{

    e[cnt].ve = v;

    e[cnt].we = w;

    e[cnt].next = head[u];

    head[u] = cnt++;

}

int main()

{

    int u, v, w;

    scanf("%d%d", &n, &m);

    memset(head,-1, sizeof(head));//-1可以用memset赋值

    for (int i = 1; i <= m; i++)

    {

         scanf("%d%d%d", &u, &v, &w);

         add(u, v, w); add(v, u, w);

    }

    return 0;

}

 

 

 

posted on 2019-05-26 01:10  Luke_Hatch0718  阅读(208)  评论(0编辑  收藏  举报