图的存储+遍历

图的存储

大家嚎,今天写到了图,先看图的存储,这里找的例题是洛谷的B3643:

题目

题目描述

给定一个 n n n 个顶点 m m m 条边的无向图。请以邻接矩阵和邻接表的形式输出这一张图。

输入格式

第一行输入两个正整数 n n n m m m,表示图的顶点数和边数。

第二行开始,往后 m m m 行,每行输入两个以空格隔开的正整数 u , v u,v u,v,表示 u , v u,v u,v 顶点之间有一条边直接相连。

输出格式

首先输出 n n n n n n 列的矩阵,以空格隔开每一行之间的数表示邻接矩阵。第 i i i 行第 j j j 列的数为 1 1 1 则表示顶点 i , j i,j i,j 之间有一条边直接相连;若为 0 0 0 则表示没有直接相连的边。

再往后输出 n n n 行。第 i i i 行首先先输出一个整数 d i d_i di,表示这个顶点的度数,再按照从小到大的顺序,依次输出与顶点 i i i 直接相连的所有顶点。

输入输出样例 #1

输入 #1
5 5
1 2
2 3
3 5
1 3
3 4
输出 #1
0 1 1 0 0
1 0 1 0 0
1 1 0 1 1
0 0 1 0 0
0 0 1 0 0
2 2 3
2 1 3
4 1 2 4 5
1 3
1 3

说明/提示

样例的图如图所示:

数据保证,对于所有数据, 1 ≤ n ≤ 1000 1 \leq n \leq 1000 1n1000 1 ≤ m ≤ 1 0 5 1 \leq m \leq 10^5 1m105,且图无重边无自环。

解答

分析

这道题题目很好理解(废话,是裸题),看到无向图矩阵就基本可以是用邻接矩阵做的题了。
大家如果不了解的话可以参考一下邻接矩阵详解,这里我就不做过多的解释了。
很简单,邻接矩阵的基础代码已经解决了两个问题,因为我们可以使用优先队列的自带函数。

答题

根据以上结论我们可以直接得出代码:

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int N=1e3+5;
int a[N][N];
vector<int> g[N];
int main() {
    int n,m;
    cin>>n>>m;
    for(int x,y,i=1;i<=m;i++) {
        cin>>x>>y;
        a[x][y]=a[y][x]=1;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for (int i=1;i<=n;i++) {
        for (int j=1;j<=n;j++) {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
    for (int i=1;i<=n;i++) {
        cout<<g[i].size()<<' ';
        sort(g[i].begin(),g[i].end());
        for (int j=0;j<g[i].size();j++) {
            cout<<g[i][j]<<' ';
        }
        cout<<endl;
    }
    return 0;
}

图的存储部分到此结束。

图的遍历

上面讲完了图的存储,但是图的存储方式不止邻接矩阵一种,还有邻接表链式前向星,这一部分我们都会用到。接下来我们继续来看图的遍历,这里找的例题是洛谷的U279163:

题目

题目描述

给出一有向图,包含n个点,编号从1-n,m条边,询问是否能从a点走到b点?

输入格式

第一行4个整数n,m,a,b 接下来m行,每行2个整数x,y,表示x到y有一条有向边

输出格式

如果能走到输出Yes,否则输出No

输入输出样例 #1

输入 #1
3 2 1 3
1 2
2 3
输出 #1
Yes

输入输出样例 #2

输入 #2
3 2 1 3
1 2
2 1
输出 #2
No

说明/提示

0 < n , m < = 200000 , a , b , x , y 保证合法 0<n,m<=200000,a,b,x,y保证合法 0<n,m<=200000,a,b,x,y保证合法

解答

分析

这道题很基础,图的遍历主要用到的是优先搜索,包括广度优先搜索深度优先搜索,我在这道题会用两种方法进行解答。

答题

1.深度优先搜索+链式前向星

#include<iostream>
using namespace std;
const int N=2e5+5,M=2e5+5;
int vis[N],h[N],cnt,n,m,a,b;
struct edge {
    int to,next;
} e[M];
void add(int x,int y) {
    cnt++;
    e[cnt].to=y;
    e[cnt].next=h[x];
    h[x]=cnt;
}
void dfs(int s) {
    vis[s]=1;
    for (int i=h[s];i!=0;i=e[i].next) {
        if (!vis[e[i].to]) {
            vis[e[i].to]=1;
            dfs(e[i].to);
        }
    }
}
int main() {
    cin>>n>>m>>a>>b;
    for (int x,y,i=0;i<m;i++) {
        cin>>x>>y;
        add(x,y);
    }
    dfs(a);
    if (vis[b]) {
        cout<<"Yes";
    }else {
        cout<<"No";
    }
    return 0;
}

2.广度优先搜索+邻接表

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
const int N=2e5+5,M=2e5+5;
vector<int> g[N];
int vis[N],n,m,a,b;
void bfs(int s) {
    queue<int> q;
    q.push(s);
    vis[s]=1;
    while (!q.empty()) {
        int t=q.front();
        q.pop();
        for (int i=0;i<g[t].size();i++) {
            if (!vis[g[t][i]]) {
                vis[g[t][i]]=1;
                q.push(g[t][i]);
            }
        }
    }
}
int main() {
    cin>>n>>m>>a>>b;
    for (int x,y,i=0;i<m;i++) {
        cin>>x>>y;
        g[x].push_back(y);
    }
    bfs(a);
    if (vis[b]) {
        cout<<"Yes";
    }else {
        cout<<"No";
    }
    return 0;
}

图的遍历部分到此结束。

结束!

我们今天写了图的存储和图的遍历的两道题,下一次我准备再分享一道图论的题,期待一下()

别走,再给个或者关注

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值