• 图的总结


    思维导图

    重要概念

    1.假设图中有n个顶点,e条边,则 含有 e=n(n-1)/2条边的无向图称作完全图; 含有 e=n(n-1)条弧的有向图称作有向完全图; 若边或弧的个数 e<nlogn,则称作稀疏图,否则称 作稠密图。

    2.假若顶点v和顶点w之间存在一条边,则称顶点v和w互为邻接点; 边(v,w)和顶点v和w相关联;和顶点v 关联的边的数目定义为边的度。

    3.对有向图来说, 顶点的出度: 以顶点v为弧尾的 弧的数目; 顶点的入度: 以顶点v为弧头的 弧的数目。 顶点的度(TD)=出度(OD)+入度(ID)

    4.简单路径:序列中顶点不重复出现 的路径。 简单回路:序列中第一个顶点和最后 一个顶点相同的路径。若图G中任意两个顶点之间都有路径相通,则称 此图为连通图;若无向图为非连通图,则图中各个极大连通子图 称作此图的连通分量。若无向图为非连通图,则图中各个极大连通子图 称作此图的连通分量。对有向图来说,若任意两个顶点之间都存在一条有向路径,则称此 有向图为强连通图。否则,其各个强连通子图称作它的强连通分量。

    5.邻接矩阵建图与深度遍历和广度遍历

    void CreateMGraph(MGraph& g, int n, int e)//建图 
    {
        g.n = n;
        g.e = e;
    
        int i, j;
    
        for (i = 1; i < g.n+1; i++) {
            for (j = 1; j < g.n+1; j++) {
                g.edges[i][j] = 0;
            }
        }
    
        int a, b;
    
        for (i = 0; i < g.e; i++) {
    
            cin >> a >> b;
    
            g.edges[a][b] = 1;
            g.edges[b][a] = 1;
        }
    
    }
    void DFS(MGraph g, int v)//深度遍历
    {
        visited[v] = 1;
    
        flag++;
        if (flag != g.n) {
            cout << v << " ";
        }
        else {
            cout << v;
        }
        
    
        for (int i = 1; i < g.n+1; ++i) {
    
            if (g.edges[v][i] != 0 && visited[i] == 0) {
    
                DFS(g, i);
            }
        }
    }
    
    void BFS(MGraph g, int v)//广度遍历
    {
        int Q[MAXV];
        int f = 0, r = 0;
        int u, w;
    
        flag += 1;
        cout << v << " ";
        visited[v] = 1;
    
        Q[r++] = v;
    
        while (r != g.n)
        {
            u = Q[f++];
            for (w = 1; w < g.n+1; w++)
            {
                if (g.edges[u][w] != 0 && visited[w] == 0)
                {
                    flag++;
                    if (flag != 2 * g.n) {
                        cout << w << " ";
                    }
                    else {
                        cout << w;
                    }
    
                    visited[w] = 1;
                    Q[r++] = w;
                }
            }
        }
    }
    

    6.邻接表建图与深度遍历和广度遍历

    void CreateAdj(AdjGraph*& G, int n, int e)//创建图邻接表
    {
        int i;
        G = new AdjGraph;
        
    
        for (i = 1; i <= n; i++) {
            G->adjlist[i].data = i;
            G->adjlist[i].firstarc = NULL;
        }
    
        int a, b;
        for (i = 0; i < e; i++) {
            cin >> a >> b;
            ArcNode* p = new ArcNode;
            p->adjvex = b;
            p->nextarc = G->adjlist[a].firstarc;
            G->adjlist[a].firstarc = p;
    
            ArcNode* q = new ArcNode;
            q->adjvex = a;
            q->nextarc = G->adjlist[b].firstarc;
            G->adjlist[b].firstarc = q;
            
        }
        G->n = n;
        G->e = e;
    }
    
    void DFS(AdjGraph* G, int v)//v节点开始深度遍历
    {
    
        visited[v] = 1;
    
        flag++;
        if (flag != G->n) {
            cout << v << " ";
        }
        else {
            cout << v;
        }
    
        ArcNode* p;
        p = G->adjlist[v].firstarc;
    
        while (p != NULL) {
    
            if (visited[p->adjvex] == 0) {
    
                DFS(G, p->adjvex);
            }
            p = p->nextarc;
        }
    }
    
    void BFS(AdjGraph* G, int v)//v节点开始广度遍历  
    {
        int Q[MAXV];
        int f = 0, r = 0;
        int u, w;
    
        flag += 1;
        cout << v << " ";
        visited[v] = 1;
    
        Q[r++] = v;
    
        ArcNode* p = new ArcNode;
        p = G->adjlist[v].firstarc;
    
        while (r != G->n)
        {
            u = Q[f++];
            p = G->adjlist[u].firstarc;
    
            while (p != NULL) {
                int n = p->adjvex;
                if (visited[n] == 0) {
                    flag++;
                    if (flag != 2 * G->n) {
                        cout << n << " ";
                    }
                    else {
                        cout << n;
                    }
    
                    visited[n] = 1;
                    Q[r++] = n;
                }
    
                p = p->nextarc;
            }
            
        }
    }
    

    疑难问题及解决方案

    公路村村通

    题目意思概括:建立一个公路图,村与村之间道路成本,建立一张带权图,并找到将每个村子连起来的路的最小成本,意思就是求最小生成是,用Prim算法来实现。

    #include <iostream>
    using namespace std;
    
    #include <stdlib.h>
    #define INF 0x7fffffff
    #define maxn 1001
    
    typedef struct _gra {
        int n, e;
        int data[maxn][maxn];
    }gra;
    void prim(gra* g, int v);
    
    int main()
    {
        gra* g = (gra*)malloc(sizeof(gra));
    
        for (int i = 0; i < maxn; i++)
            for (int j = 0; j < maxn; j++) {
                if (i == j)
                    g->data[i][j] = 0;
                else g->data[i][j] = INF;
            }
    
        int n, m, k, p, c;
        cin >> n >> m;
        g->n = n;
        g->e = m;
    
        for (int i = 0; i < m; i++) {
            cin >> k >> p >> c; 
            g->data[k][p] = g->data[p][k] = c;
        }
    
        if (m < n - 1)printf("-1");
        else
            prim(g, 1);
        return 0;
    }
    
    void prim(gra* g, int v) {
    
        int sum = 0;
        int lowcost[maxn];
        int close[maxn];
    
        for (int i = 1; i <= g->n; i++) {
            lowcost[i] = g->data[v][i];
            close[i] = v;
        }
        lowcost[v] = 0;
    
        for (int i = 2; i <= g->n; i++) {
            int min = INF, k = 0;
            for (int j = 1; j <= g->n; j++) {
                if (lowcost[j] < min && lowcost[j] != 0) {
                    min = lowcost[j];
                    k = j;
                }
            }
            sum += lowcost[k];
            lowcost[k] = 0;
            for (int j = 1; j <= g->n; j++) {
                if (lowcost[j] != 0 && g->data[k][j] < lowcost[j]) {
                    lowcost[j] = g->data[k][j];
                    close[j] = k;
                }
            }
        }
    
        int flag = 0;
        for (int i = 1; i <= g->n; i++) {
            if (lowcost[i] == INF) {
                flag = 1;
                break;
            }
        }
    
        if (flag)cout << "-1";
        else cout << sum; 
    }
    
  • 相关阅读:
    KOL运营之——如何与网文作者高效地约稿?
    C#利用反射来判断对象是否包含某个属性的实现方法
    MySQL数据库忘记密码
    MySQL基本概念以及简单操作
    .net Mvc框架原理
    跨域资源共享 CORS 详解
    DOM 操作技术【JavaScript高级程序设计第三版】
    关于在"a"标签中添加点击事件的一些问题
    Visual Studio 2017各版本安装包离线下载、安装全解析
    详解Session分布式共享(.NET CORE版)
  • 原文地址:https://www.cnblogs.com/jiuweihong/p/12880958.html
Copyright © 2020-2023  润新知