算法与数据结构:图的基本概念及存储方式

今天学习了代码源初级包图论的第一节课,图的基本概念及存储方式。

基本概念:

一个图是由点集 V V V和边集 E E E组成的,一般会记作为图 G = < V , E > G=<V,E> G=<V,E>,一条边连接两个顶点。

点集 V V V包含了所有顶点,边集 E E E包含了所有边,点集 V V V为空时称为空图。

全部由无向边构成的图称为无向图,由有向图构成的图称为有向图,有向边可以理解为单行道。

自环:边连接的两个点是同一个点。

重边:无向图中指在两点之间有多条边 ( ≥ 2 ) (\geq2) (2)连接,如果是有向图则是在两点之间有多条同方向的边 ( ≥ 2 ) (\geq2) (2)连接。

孤点:没有连接边的点。

简单图:没有自环和重边的图称为简单图。

度数

无向图的度数:对于无向图中的顶点 v v v v v v作为边的端点的次数称为 v v v的度数,记为 d ( v ) d(v) d(v)

有向图的度数:对于有向图的顶点 v v v v v v作为边的起点的次数称为 v v v出度,记为 d + ( v ) d^+(v) d+(v) v v v作为边的终点的次数称为 v v v入度,记为 d − ( v ) d^-(v) d(v);顶点 v v v的度数 d ( v ) = d + ( v ) + d − ( v ) d(v)=d^+(v)+d^-(v) d(v)=d+(v)+d(v)

每个图 G G G的最大度为所有顶点度数的最大值,记做 Δ ( G ) \Delta(G) Δ(G);最小度为所有顶点度数的最小值,记做 δ ( G ) \delta(G) δ(G)

一张图的所有点的度数和为边数的两倍,有向图所有顶点的出度和等于入度和。

完全图和竞赛图

完全图(无向图):设 G G G为一个有 n n n个节点的无向简单图,若 G G G中每一个顶点都与其余 n − 1 n-1 n1个顶点有边相连,则称 G G G为** n n n阶无向完全图**,简称为** n n n阶完全图**,记做 k n k_n kn,一共有 C n 2 C_n^2 Cn2条边。

完全图(有向图):设 G G G为一个有 n n n个节点的有向简单图,若 G G G中每个顶点都有连到其余 n − 1 n-1 n1个顶点的边,且都有这些节点连向它的边,则称 G G G为** n n n阶有向完全图**,一共有 n ( n − 1 ) n(n-1) n(n1)条边。

竞赛图:基于** n n n阶无向完全图**,给每条边任意一个方向形成的图称为** n n n阶竞赛图**。

子图、生成子图

子图:设 G = < V , E > , G ′ = < V ′ , E ′ > G=<V,E>,G^{'}=<V^{'},E^{'}> G=<V,E>,G=<V,E>为两个图(同为无向图或者有向图),如果 V ′ ⊆ V V^{'}\subseteq V VV E ′ ⊆ E E^{'}\subseteq E EE,则称图 G ′ G^{'} G为图 G G G子图 G G G称为图 G ′ G^{'} G母图,记做 G ′ ⊆ G G^{'}\subseteq G GG

如果 V ′ = V V^{'}=V V=V,则称 G ′ G^{'} G G G G生成子图

如果 V ′ ⊂ V V^{'}\sub V VV或者 E ′ ⊂ E E^{'}\sub E EE,则称 G ′ G^{'} G G G G真子图

补图

补图:设 G = < V , E > G=<V,E> G=<V,E>是一个 n n n阶无向简单图,以 V V V为顶点集,以所有使 G G G成为完全图 K n K_n Kn需要添加的边的集合为边集的图,称为 G G G补图,记做 G ˉ \bar{G} Gˉ

简单来说:图和它的补图顶点集相同;边集的交集为空,并集是完全图的边集。

同构

同构定义:设 G G G G ′ G^{'} G是分别具有顶点集 V V V V ′ V^{'} V的两个图。如果存在一个双射 h : V → V ′ h:V\to V^{'} h:VV满足当且仅当 ( v i , v j ) (v_i,v_j) (vi,vj) G ′ G^{'} G的边时, ( h ( v i ) , h ( v j ) ) (h(v_i),h(v_j)) (h(vi),h(vj)) G ′ G^{'} G的边,则称图 G G G G ′ G^{'} G同构。

通路、回路、路径和距离

对于一个图 G G G G G G中顶点与边的交替序列 v 0 e 1 v 1 e 2 v 2 e 3 v 3 … e n v n v_0e_1v_1e_2v_2e_3v_3\ldots e_nv_n v0e1v1e2v2e3v3envn称为 v 0 v_0 v0 v n v_n vn的通路,其中 v 0 , v n v_0,v_n v0,vn称为通路的起点和终点,通路中边的条数称为它的长度。在有向图中,要保持边的方向一致。

对于一条通路,如果 v 0 = v n v_0=v_n v0=vn,则称为回路。如果 v 0 = v n v_0=v_n v0=vn且其他所有顶点都不相同,则称为环。

如果通路中的所有边都不相同,称为。如果通路中的所有顶点都不相同,边也各不相同,则称为路径

图中连接两点之间最短的路径长度称为距离

连通性和连通块

无向图

连通性:设无向图 G = < V , E > , u , v ∈ V G=<V,E>,u,v\in V G=<V,E>,u,vV,如果 u , v u,v u,v之间存在通路,则称 u , v u,v u,v连通的。对于$\forall v\in V , , v和v$自己是连通的。

连通图:对于任意非空无向图 G G G,若 G G G中任意两个顶点都是连通的,则称 G G G为连通图。

连通块:对于无向图 G G G的一个连通子图 H H H,如果不存在 F F F满足 H ⊂ F ⊆ G H\sub F \subseteq G HFG F F F为连通图,则称 H H H G G G的一个连通块/连通分量, H H H是一个极大连通子图。

有向图

连通性:设有向图 G = < V , E > , u , v ∈ V G=<V,E>,u,v\in V G=<V,E>,u,vV,如果 u , v u,v u,v之间存在通路,则称 u u u可达 v v v。如果 u , v u,v u,v相互可达,则称 u , v u,v u,v连通

强联通:如果有向图 G G G中的顶点两两可达,可以定义有向图的强联通块/强连通分量

强连通块:与无向图的类似,可以定义有向图的强联通块/强连通分量

图的存储方式

邻接矩阵:a[x][y]

邻接表:vector<int> edge[N];

题目

简单图的判定:

简单图判定

在这里插入图片描述

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n' //交互题删掉
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
const int N = 1010;
int a[N][N];
int n, m;
void solve()
{
    cin >> n >> m;
    bool ok = 1;
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (x == y || a[x][y])
        {
            ok = 0;
        }
        a[x][y] = a[y][x] = 1;
    }
    if (!ok)
    {
        cout << "No" << endl;
    }
    else
    {
        cout << "Yes" << endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

顶点度数统计:

顶点度数统计

在这里插入图片描述

代码如下:

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n' //交互题删掉
#define x first
#define y second
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
const int N = 1e3 + 10;
int n, m;
int din[N], dout[N];
void solve()
{
    cin >> n >> m;
    while (m--)
    {
        int a, b;
        cin >> a >> b;
        din[b]++;
        dout[a]++;
    }
    for (int i = 1; i <= n; i++)
    {
        cout << din[i] + dout[i] << " \n"[i == n];
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}

顶点度数合法性:

顶点度数合法性

在这里插入图片描述

/*
coder:sunshine
school:njupt
*/
#include <bits/stdc++.h>
using namespace std;
#define endl '\n' //交互题删掉
#define x first
#define y second
typedef long long ll;
typedef pair<int, int> pii;
const int mod = 1e9 + 7;
int n;
void solve()
{
    cin >> n;
    ll sum = 0;
    for (int i = 1; i <= n; i++)
    {
        int a;
        cin >> a;
        sum += a;
    }
    if (sum & 1)
    {
        cout << "No" << endl;
    }
    else
    {
        cout << "Yes" << endl;
    }
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    t = 1;
    while (t--)
    {
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值