图的总结

思维导图

 

重要概念

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; 
}
posted @ 2020-05-17 08:27  违久(丁鸿沛)  阅读(218)  评论(0编辑  收藏  举报