图论问题的算法 (C++)

C++基础图论算法大集合 (图论,看我就行了) 图论搜索技术深度优先搜索 (应用——求重心)广度优先搜索 (应用——图中的层次遍历)有向图的拓扑排序最短路问题Dijkstra算法(朴素版)Dijkstra算法 (堆优化)bellman_ford算法spfa算法spfa判负权Floyd算法最小生成树系列prim算法二分图判断二分图(染色法)二分图的最大匹配 搜索技术 深度优先搜索 (应用——求重心) 重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。 本题的本质是树的dfs, 每次dfs可以确定以u 阅读详情

以下题目和算法思路均来自AcWing
这个文章当作我的笔记了,方便以后的复习
在这里再次感谢y总

图论问题的算法

有向图的拓扑排序

AcWing 848.有向图的拓扑序列

给定一个 n n n个点 m m m条边的有向图,点的编号是 1 1 1到 n n n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 − 1 −1 −1。

若一个由图中所有点构成的序列 A A A满足:对于图中的每条边 ( x , y ) (x,y) (x,y), x x x在 A A A中都出现在 y y y之前,则称 A A A是该图的一个拓扑序列。

输入格式
第一行包含两个整数 n n n和 m m m。

接下来 m m m行,每行包含两个整数 x x x和 y y y,表示存在一条从点 x x x到点 y y y的有向边 ( x , y ) (x,y) (x,y)。

输出格式
共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

否则输出 − 1 −1 −1。

数据范围
1 ≤ n , m ≤ 105 1≤n,m≤105 1≤n,m≤105
输入样例:

3 3
1 2
2 3
1 3

输出样例:

1 2 3

通过入度的数量来判断当前的点是否是该输出

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>

using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N], ne[N], idx;
int din[N];                     // 入度的大小
vector<int> ans;

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

void topsort() {
    queue<int> store;
    for (int i = 1; i <= n; i++)
        if (din[i] == 0)
            store.push(i);

    while (store.size()) {
        auto t = store.front();
        store.pop();
        
        ans.push_back(t);

        for (int i = h[t]; ~i; i = ne[i]) {
            int j = e[i];
            if (--din[j] == 0)
                store.push(j);
        }
    }
}

int main() {
    memset(h, -1, sizeof h);
    cin >> n >> m;
    for (int i = 0; i < m; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        add(x, y);
        din[y]++;
    }

    topsort();

    if (ans.size() != n) cout << "-1" << endl;
    else {
        for (int i = 0, len = ans.size(); i < len; i++)
            printf("%d ", ans[i]);
    }
    return 0;
}

单源最短路径算法

dijkstra

AcWing 849. Dijkstra求最短路 I

给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环,所有边权均为正值。

请你求出 1 1 1 号点到 n n n 号点的最短距离,如果无法从 1 1 1 号点走到 n n n 号点,则输出 − 1 −1 −1。

输入格式
第一行包含整数 n n n 和 m m m。

接下来 m m m行每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z。

输出格式
输出一个整数,表示 1 1 1 号点到 n n n 号点的最短距离。

如果路径不存在,则输出 − 1 −1 −1。

数据范围
1 ≤ n ≤ 500 1≤n≤500 1≤n≤500,
1 ≤ m ≤ 105 1≤m≤105 1≤m≤105,
图中涉及边长均不超过 10000 10000 10000。

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

算法的步骤:

  1. 寻找路径最小的点
  2. 用这个点更新他的周围的点
  3. 将点添加到路径中

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 510;

int n, m;
int g[N][N];	// 从i到j的距离
int dist[N];	// 到起点的距离
bool st[N];		// 是否已经被遍历过

void dijkstra(int start) {
    memset(dist, 0x3f, sizeof dist);												// 初始化距离
    dist[start] = 0;

    for (int i = 0; i < n - 1; i ++) {
        int minv = -1;
        for (int j = 1; j <= n; j++)                        // 寻找路径最小的点
            if (!st[j] && (minv == -1 || dist[minv] > dist[j]))
                minv = j;

        for (int j = 1; j <= n; j++)                        // 用这个点更新周围的点
            dist[j] = min(dist[j], dist[minv] + g[minv][j]);

        st[minv] = true;                                    // 将点添加到路径中
    }
}

int main() {
    memset(g, 0x3f,sizeof g);   //初始化地图

    cin >> n >> m;
    while (m--) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        g[x][y] = min(g[x][y], z);
    }

    dijkstra(1);

    if (dist[n] == 0x3f3f3f3f)
        cout << -1 << endl;
    else
        cout << dist[n] << endl;

    return 0;
}

dijkstra堆优化版

AcWing 850. Dijkstra求最短路 II

给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环,所有边权均为非负值。

请你求出 1 1 1 号点到 n n n 号点的最短距离,如果无法从 1 1 1 号点走到 n n n 号点,则输出 − 1 −1 −1。

输入格式
第一行包含整数 n n n 和 m m m。

接下来 m m m 行每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z。

输出格式
输出一个整数,表示 1 1 1 号点到 n n n 号点的最短距离。

如果路径不存在,则输出 − 1 −1 −1。

数据范围
1 ≤ n , m ≤ 1.5 × 1 0 5 1≤n,m≤1.5×10^{5} 1≤n,m≤1.5×105,
图中涉及边长均不小于 0 0 0,且不超过 10000 10000 10000。
数据保证:如果最短路存在,则最短路的长度不超过 1 0 9 10^{9} 109。

输入样例:

3 3
1 2 2
2 3 1
1 3 4

输出样例:

3

用堆可以优化查找最小路径的这个过程

C++代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 150010;

int n, m;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void dijkstra(int start) {
    priority_queue<PII, vector<PII>, greater<PII>> store;
    memset(dist, 0x3f, sizeof dist);
    dist[start] = 0;
    store.push({0, start});

    while (store.size()) {
        auto temp = store.top();								// 获取最短路径的点
        store.pop();

        int distance = temp.x, ver = temp.y;

        if (st[ver]) continue;									// 将点添加到路径中
        st[ver] = true;

        for (int i = h[ver]; ~i; i = ne[i]) {		// 更新这个点连接的点的距离
            int j = e[i];
            if (dist[j] > dist[ver] + w[i]) {
                dist[j] = dist[ver] + w[i];
                store.push({dist[j], j});
            }
        }
    }
}

int main() {
    memset(h, -1, sizeof h);   //初始化地图

    cin >> n >> m;
    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }

    dijkstra(1);

    if (dist[n] == 0x3f3f3f3f)
        cout << -1 << endl;
    else
        cout << dist[n] << endl;

    return 0;
}

Bellman-Ford

AcWing 853. 有边数限制的最短路

给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你求出从 1 1 1 号点到 n n n 号点的最多经过 k k k 条边的最短距离,如果无法从 1 1 1 号点走到 n n n 号点,输出 i m p o s s i b l e impossible impossible。

注意:图中可能 存在负权回路 。

输入格式
第一行包含三个整数 n , m , k n,m,k n,m,k。

接下来 m m m 行,每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z。

输出格式
输出一个整数,表示从 1 1 1 号点到 n n n 号点的最多经过 k k k 条边的最短距离。

如果不存在满足条件的路径,则输出 i m p o s s i b l e impossible impossible。

数据范围
1 ≤ n , k ≤ 500 1≤n,k≤500 1≤n,k≤500,
1 ≤ m ≤ 10000 1≤m≤10000 1≤m≤10000,
任意边长的绝对值不超过 10000 10000 10000。

输入样例:

3 3 1
1 2 1
2 3 1
1 3 3

输出样例:

3

bellman-ford比dijkstra更有广泛性, 他处理的图可以有负权边,dijkstra则不可以

核心思想:

对所有的边进行n-1轮松弛操作,因为在一个含有n个顶点的图中,任意两点之间的最短路径最多包含n-1边。换句话说,第1轮在对所有的边进行松弛后,得到的是源点最多经过一条边到达其他顶点的最短距离;第2轮在对所有的边进行松弛后,得到的是源点最多经过两条边到达其他顶点的最短距离;第3轮在对所有的边进行松弛后,得到的是源点最多经过一条边到达其他顶点的最短距离…

https://zhuanlan.zhihu.com/p/72185593

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 510, M = 10010, INF = 0x3f3f3f3f;

int n, m, k;
int h[N], e[M], ne[M], w[M], idx;
int dist[N], backup[N];

void add(int a, int b, int c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void bellman_ford(int start) {
    memset(dist, 0x3f,sizeof dist);
    dist[start] = 0;
    for (int v = 0; v < k; v++){
        memcpy(backup, dist, sizeof dist);
        for (int i = 1; i <= n; i++)
            for (int j = h[i]; ~j; j = ne[j]) {
                int t = e[j];
                dist[t] = min(dist[t], backup[i] + w[j]);   // 松弛操作
            }
    }
}

int main() {
    memset(h, -1, sizeof h);

    cin >> n >> m >> k;
    while (m --) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        add(x, y, z);
    }

    bellman_ford(1);

    if (dist[n] > INF / 2) cout << "impossible" << endl;
    else cout << dist[n] << endl;

    return 0;
}

SPFA

AcWing 851. spfa求最短路

给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。

请你求出 1 1 1 号点到 n n n 号点的最短距离,如果无法从 1 1 1 号点走到 n n n 号点,则输出 i m p o s s i b l e impossible impossible。

数据保证不存在负权回路。

输入格式
第一行包含整数 n n n 和 m m m。

接下来 m m m 行每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z。

输出格式
输出一个整数,表示 1 1 1 号点到 n n n 号点的最短距离。

如果路径不存在,则输出 i m p o s s i b l e impossible impossible。

数据范围
1 ≤ n , m ≤ 1 0 5 1≤n,m≤10^{5} 1≤n,m≤105,
图中涉及边长绝对值均不超过 10000 10000 10000。

输入样例:

3 3
1 2 5
2 3 -3
1 3 4

输出样例:

2

堆优化版的bellman-ford算法, 在最坏的情况下和bellman-ford算法是一个复杂度

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>

using namespace std;

const int N = 100010, INF = 0x3f3f3f3f;

int n, m;
int h[N], e[N], ne[N], w[N], idx;
int dist[N];
bool st[N];

void add(int a, int b, int c) {
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++;
}

void spfa(int start) {
    memset(dist, 0x3f,sizeof dist);
    dist[start] = 0;
    queue<int> store;
    store.push(start);
    st[start] = true;

    while (store.size()) {
        int temp = store.front();
        store.pop();

        st[temp] = false;
        for (int i = h[temp]; ~i; i = ne[i]) {
            int j = e[i];
            if (dist[j] > dist[temp] + w[i]) {  // 松弛操作
                dist[j] = dist[temp] + w[i];
                if (!st[j]) {                   // 当队列中没有当前的点的时候才会添加
                    store.push(j);
                    st[j] = true;
                }
            }
        }
    }
}

int main() {
    memset(h, -1, sizeof h);

    cin >> n >> m;
    while (m--) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
    }

    spfa(1);

    if (dist[n] > INF / 2) cout << "impossible" << endl;
    else cout << dist[n] << endl;

    return 0;
}

多源最短路算法

Floyed

AcWing 854. Floyd求最短路

给定一个 n n n 个点 m m m 条边的有向图,图中可能存在重边和自环,边权可能为负数。

再给定 k k k 个询问,每个询问包含两个整数 x x x 和 y y y,表示查询从点 x x x 到点 y y y 的最短距离,如果路径不存在,则输出 i m p o s s i b l e impossible impossible。

数据保证图中不存在负权回路。

输入格式
第一行包含三个整数 n , m , k n,m,k n,m,k。

接下来 m m m 行,每行包含三个整数 x , y , z x,y,z x,y,z,表示存在一条从点 x x x 到点 y y y 的有向边,边长为 z z z。

接下来 k k k 行,每行包含两个整数 x , y x,y x,y,表示询问点 x x x 到点 y y y 的最短距离。

输出格式
共 k k k 行,每行输出一个整数,表示询问的结果,若询问两点间不存在路径,则输出 i m p o s s i b l e impossible impossible。

数据范围
1 ≤ n ≤ 200 1≤n≤200 1≤n≤200,
1 ≤ k ≤ n 2 1≤k≤n2 1≤k≤n2
1 ≤ m ≤ 20000 1≤m≤20000 1≤m≤20000,
图中涉及边长绝对值均不超过 10000 10000 10000。

输入样例:

3 3 2
1 2 1
2 3 2
1 3 1
2 1
1 3

输出样例:

impossible
1

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;

int n, m, k;
int g[N][N];

void floyed() {
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1 ; j <= n; j++)
                g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
}

int main() {
    memset(g, 0x3f,sizeof g);
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
        g[i][i] = 0;
        
    for (int i = 1; i <= m; i++) {
        int x, y, z;
        scanf("%d%d%d", &x, &y, &z);
        g[x][y] = min(g[x][y], z);
    }

    floyed();

    while (k--) {
        int x, y;
        scanf("%d%d", &x, &y);
        if (g[x][y] > INF / 2) printf("impossible\n");
        else printf("%d\n", g[x][y]);
    }

    return 0;
}

最小生成树算法

prim

AcWing 858. Prim算法求最小生成树

给定一个 n n n 个点 m m m 条边的无向图,图中可能存在重边和自环,边权可能为负数。

求最小生成树的树边权重之和,如果最小生成树不存在则输出 i m p o s s i b l e impossible impossible。

给定一张边带权的无向图 G = ( V , E ) G=(V,E) G=(V,E),其中 V 表示图中点的集合, E E E 表示图中边的集合, n = ∣ V ∣ n=|V| n=∣V∣, m = ∣ E ∣ m=|E| m=∣E∣。

由 V V V 中的全部 n n n 个顶点和 E E E 中 n − 1 n−1 n−1 条边构成的无向连通子图被称为 G G G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G G G 的最小生成树。

输入格式
第一行包含两个整数 n n n 和 m m m。

接下来 m m m 行,每行包含三个整数 u , v , w u,v,w u,v,w,表示点 u u u 和点 v v v 之间存在一条权值为 w w w 的边。

输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出 i m p o s s i b l e impossible impossible。

数据范围
1 ≤ n ≤ 500 1≤n≤500 1≤n≤500,
1 ≤ m ≤ 1 0 5 1≤m≤10^{5} 1≤m≤105,
图中涉及边的边权的绝对值均不超过 10000 10000 10000。

输入样例:

4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4

输出样例:

6

普里姆算法查找最小生成树的过程,采用了贪心算法的思想。对于包含 N 个顶点的连通网,普里姆算法每次从连通网中找出一个权值最小的边,这样的操作重复 N-1 次,由 N-1 条权值最小的边组成的生成树就是最小生成树。

http://c.biancheng.net/algorithm/prim.html

算法步骤

  1. 初始化距离,将他初始化为正无穷
  2. n次迭代
    1. 找到不在集合中的距离最小的点 t t t
    2. 用 t t t 来更新其他点到集合的距离
    3. 把 t t t 加到集合中

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>

using namespace std;

const int N = 510, INF = 0x3f3f3f3f;

int n, m;
int g[N][N];
int dist[N];
bool st[N];

int prim() {
    memset(dist, 0x3f,sizeof dist);

    int res = 0;
    for (int i = 0; i < n; i++) {
        int t = -1;
        for (int j = 1; j <= n; j++) {
            if (!st[j] && (t == -1 || dist[t] > dist[j]))
                t = j;
        }

        if (i && dist[t] == INF) return INF;

        if (i) res += dist[t];
        st[t] = true;

        for (int j = 1; j <= n; j++) dist[j] = min(dist[j], g[t][j]);
    }

    return res;
}

int main() {
    memset(g, 0x3f,sizeof g);

    cin >> n >> m;
    
    for (int i = 1; i <= n; i++) g[i][i] = 0;
    
    while (m--) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        g[u][v] = min(g[u][v], w);
        g[v][u] = min(g[v][u], w);
    }

    int sum = prim();
    if (sum == INF) cout << "impossible" << endl;
    else cout << sum << endl;
    return 0;
}

Kruskal

AcWing 859. Kruskal算法求最小生成树

给定一个 n n n 个点 m m m 条边的无向图,图中可能存在重边和自环,边权可能为负数。

求最小生成树的树边权重之和,如果最小生成树不存在则输出 i m p o s s i b l e impossible impossible。

给定一张边带权的无向图 G = ( V , E ) G=(V,E) G=(V,E),其中 V 表示图中点的集合, E E E 表示图中边的集合, n = ∣ V ∣ n=|V| n=∣V∣, m = ∣ E ∣ m=|E| m=∣E∣。

由 V V V 中的全部 n n n 个顶点和 E E E 中 n − 1 n−1 n−1 条边构成的无向连通子图被称为 G G G 的一棵生成树,其中边的权值之和最小的生成树被称为无向图 G G G 的最小生成树。

输入格式
第一行包含两个整数 n n n 和 m m m。

接下来 m m m 行,每行包含三个整数 u , v , w u,v,w u,v,w,表示点 u u u 和点 v v v 之间存在一条权值为 w w w 的边。

输出格式
共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出 i m p o s s i b l e impossible impossible。

数据范围
1 ≤ n ≤ 1 0 5 1≤n≤10^{5} 1≤n≤105,
1 ≤ m ≤ 2 ∗ 1 0 5 1≤m≤2∗10^{5} 1≤m≤2∗105,
图中涉及边的边权的绝对值均不超过 1000 1000 1000。

输入样例:

4 5
1 2 1
1 3 2
1 4 3
2 3 2
3 4 4

输出样例:

6

适合稀疏图

算法思路:

  1. 先将所有的边按权重从小到大的进行排序
  2. 枚举每条边 ( a , b ) (a, b) (a,b) 权重是 c c c 若 a , b a,b a,b 不连通,则将这条边加入到集合中

C++ 代码

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 200010;

int n, m;
int p[N];

struct Edge {
    int a, b, w;

    bool operator< (const Edge &W) const {
        return w < W.w;
    }
}edges[N];

int find(int x) {
    if (p[x] != x) p[x] = find(p[x]);
    return p[x];
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        int a, b, w;
        scanf("%d%d%d", &a, &b, &w);
        edges[i] = {a, b, w};
    }

    sort(edges, edges + m);

    for (int i = 1; i <= n; i++) p[i] = i;

    int res = 0, cnt = 0;   // 最小生成树的所有数边的权重之和, 加入的边数
    for (int i = 0; i < m; i++) {
        int a = edges[i].a, b = edges[i].b, w = edges[i].w;

        a = find(a), b = find(b);
        if (a != b) {
            p[a] = b;   // 将两个点合并
            res += w;
            cnt++;
        }
    }
    if (cnt < n - 1) cout << "impossible" << endl;
    else cout << res << endl;
}

染色法判定二分图

AcWing 860. 染色法判定二分图

给定一个 n n n 个点 m m m 条边的无向图,图中可能存在重边和自环。

请你判断这个图是否是二分图。

输入格式
第一行包含两个整数 n n n 和 m m m。

接下来 m m m 行,每行包含两个整数 u u u 和 v v v,表示点 u u u 和点 v v v 之间存在一条边。

输出格式
如果给定图是二分图,则输出 Y e s Yes Yes,否则输出 N o No No。

数据范围
1 ≤ n , m ≤ 1 0 5 1≤n,m≤10^{5} 1≤n,m≤105
输入样例:

4 4
1 3
1 4
2 3
2 4

输出样例:

Yes

C++ 代码

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

const int N = 100010;

int n, m;
int h[N], e[N * 2], ne[N * 2], idx;
int g[N];

void add(int a, int b) {
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

bool dfs(int u, int a) {
    g[u] = a;
    for (int i = h[u]; ~i; i = ne[i]) {
        int j = e[i];
        if (!g[j]) {
            if(!dfs(j, 3 - a)) return false;
        }
        else if (g[j] == a) return false;
    }
    return true;
}

int main() {
    memset(h, -1, sizeof h);
    cin >> n >> m;
    while (m--) {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v);
        add(v, u);
    }

    bool flag = true;
    for (int i = 1; i <= n; i++) {
        if (!g[i]) {
            if(!dfs(i, 1)){
                flag = false;
                break;
            }
        }
    }

    if (flag) cout << "Yes" << endl;
    else cout << "No" << endl;
}

笔记

最短路和最小生成树的区别

最小生成数能保证整个拓扑图的所有路径之和最小, 但不能保证任意两点之间是最短路径

最短路径是从一点出发, 到达目的地的路径最小

单源最短路和多源最短路的区别

单源最短路: 从一个点出发到任意一个点的距离最短

多源最短路: 从任意点出发到任意点的距离最短

C++ 图论之Floyd算法求解次最短路径的感悟,一切都是脱壳后找最值而已 抛开基因的影响,学霸和学渣到底是在哪一点上有差异?学霸刷完200道题,会对题目分类,并总结出解决类型问题的通用模板,我不喜欢模板这个名词,感觉到投机的意味,或许用方法或通用表达式更高级一点。而事实上模板一词更准确。每一道题目在描述时,会套上一堆场景说词,可以说是契合真正的应用领域,或者说是出题人的故弄玄虚,弄了一些花里胡哨的迷糊你的外表,这时考核的不是专业知识,而是语文阅读能力。一旦脱出外壳,露出来的底层需求,就是书本上最基础的知识。 阅读详情

相关推荐

c++基础算法(认识图论)

图论是数学中的一个分支,研究图的性质和图的相关问题。图是由节点和连接节点的边组成的结构,节点表示对象,边表示对象之间的关系。

sjzwer_的博客 1592

【图论】总汇(内含C++)

图由点和边组成的。有向图、有向边,是有方向的。度是一点所关联的边数。出度有向图中,从一个点出去的边数;入度有向图中,从一个点进来的边数。自环,邪恶的东西,能寄掉一些算法,需要特殊处理,一条边两端连着同一个点。路径,从一个点走到另一个点(可含环);简单路径,就是不含环的路径。环,从一点出发在绕回这个点的路径有向无环图(DAG),若设动态规划状态为点,转移为为边,这一定是DAG。需要用邻接接矩阵。表示从 j 走到 k 经过的点的编号小于等于 i 的最短路。通过一个点,将周围所有点最短路变短。

weixin_66767924的博客 5176

算法(C++)金币阵列问题

题目描述 有m × n(m ≤ 100 ,n ≤ 100) 个金币在桌面上排成一个m 行n 列的金币阵列。每一枚金币或正面朝上或背面朝上。用数字表示金币状态,0 表示金币正面朝上,1 表示背面朝上。 金币阵列游戏的规则是: (1)每次可将任一行金币翻过来放在原来的位置上; (2)每次可任选2 列,交换这2 列金币的位置。 编程任务 给定金币阵列的初始状态和目标状态,编程计算按金币游戏规则,将金币阵...

qiqi_miao的博客 5386

ACWING 848. 有向图的拓扑序列(拓扑排序)

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。 请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。 若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。 输入格式 第一行包含两个整数 n 和 m。 接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)。 输出格式 共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

这是博客描述 872

算法——弗洛伊德算法(Floyd-Warshall)(图论)(c++)

(蒟蒻的第四篇文章,希望dalao勿喷) (希望没问题) 声明: 1.本人变量定义的名称很low 2.本人用的方法也很low 3.但我觉得文章应该不low(盲目自信) 第四篇文章讲讲Floyd算法 Floyd算法是一种寻找最短路径的常见算法,其特点是:短,好理解(虽然其他算法也挺好理解的 思路 Floyd算法的主要思路是在于: 比如你要坐飞机从A城到B城,结果你发现A到B的直达航班要999元!于是你漫无目的地继续看其他航班信息,结果突然发现在A和B中间,还有一个C城!而且A到C和B到C.

Passerby_XX的博客 2928

图论入门算法:拓扑排序(C++)

本文介绍图论中的拓扑排序算法, 介绍Kahn算法和DFS算法两种实现方式. 通过图解和代码希望能帮助读者理解.

一些C++相关的技术笔记或者教程. 1921

【No.17】蓝桥杯图论上|最短路问题|Floyd算法|Dijkstra算法|蓝桥公园|蓝桥王国(C++)

因为最小边的不会被其它的点松弛,只有可能最小边去松弛别人。如果存在一个点 K 能够松弛 ab 的话那么一定有 ak 距离加上 kb 的距离小于 ab,已知 ab 最短,所以不存在 ak+kb

ChoSeitaku的博客 1911

工业视觉开发者的福音:用C#玩转VisionMaster算子(非方案版完整教程)

本文为工业视觉开发者提供了一份完整的C#与VisionMaster算子二次开发教程,详细介绍了环境配置、算子调用原理、性能优化技巧及实战案例。通过模板匹配和二维码识别等实例,展示了如何高效集成VisionMaster算子到现有框架中,提升工业自动化视觉检测系统的灵活性和性能。

weixin_29280657的博客 273

【No.18】蓝桥杯图论下|Bellman-Ford算法|SPFA算法|最小生成树|Prim算法|Kruskal算法|随机数据下的最短路问题|路径|聪明的猴子(C++)

Dijkstra:适用于权值为非负的图的单源最短路径,用小顶堆的复杂度O(E+VlgV)BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE)SPFA:适用于权值有负值,且没有负圈的图的单源最短路径。论文中的复杂度为O(kE), 其中k为每个节点进入队列的次数,且k一般

ChoSeitaku的博客 1160

基于 OptiSystem 的掺铒光纤放大器(EDFA)分析

通过构建 EDFA 仿真模型,系统分析了铒离子掺杂半径、离子浓度、光纤长度及泵浦功率等关键参数对放大器增益和噪声特性的影响规律,为 EDFA 的优化设计提供了理论依据与仿真支撑。继续增大至 9μm,增益趋于稳定(约 19dB)。继续增加至 200mW,增益仅增加 2dB,表明泵浦功率存在阈值效应(约 100mW),超过后增益饱和明显。:作为增益介质,主要参数包括光纤长度(5~50m)、铒离子掺杂半径(1~10μm)、离子浓度(1×10²⁵~5×10²⁵m⁻³)、纤芯半径 2.2μm、数值孔径 0.24。

2501_91855190的博客 2678

SwissADME:一款在线预测小分子药动学性质的工具

是一个免费的在线工具,由瑞士生物信息学研究所(SIB)开发,用于预测和分析小分子的药物相似性、理化性质、药代动力学特性以及合成可行性等。它是药物设计和开发中常用的工具之一,帮助研究人员快速评估化合物的成药潜力。

药研猿的博客 5022

2021年第十二届蓝桥杯省赛B组(C/C++)第二场题解

2021年第十二届蓝桥杯省赛B组(C/C++)第二场题解

涛涛的个人博客 2916

vivado 工程修改芯片型号

vivado工程芯片与实际板子不匹配时,需要修改工程的芯片型号,并对原工程的ip进行同步更新,之后生成新的bit文件,烧录到板子中

k7126685的博客 1万+

图论算法简单总结(C++)

本篇内容来源于代码随想录。最小生成树是所有节点的最小连通子图,即:以最小的成本(边的权值)将图中所有节点链接到一起。给出一个有向图,把这个有向图转成线性的排序就叫拓扑排序。拓扑排序也是图论中判断有向无环图的常用方法。

qq_45835091的博客 1395

UCOS-III 系统移植

UCOSIII系统移植到GD32F303详细过程 工程代码:https://github.com/jslaobing/techIot_ucosiii_porting

TechIoT - 探索物联网与嵌入式系统 2087

STM32CubeMX的正交编码器encoder

由于最近干活遇到需要获取正交编码的功能,所以返回来研究一下STM32CubeMX的编码器功能,之前也更新过STM32的定时器功能,但是因为之前搞平衡车的正交编码器没有搞清楚原理,就直接用了脉冲输入功能草草了事,现在也算是为之前的年轻买单了,不过看到现有的Encoder说明都比较简单,所以就当是为开发者做贡献了,我研究清楚之后来一篇博客。

ASWaterbenben的博客 1万+

匈牙利算法——图论(C++)

一、基本概念 1、匹配:在图论中,一个「匹配」是一个边的集合,其中任意两条边都没有公共顶点。 2、最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配。 3、完美匹配:如果一个图的某个匹配中,所有的顶点都是匹配点,那么它就是一个完美匹配。 4、交替路:从一个未匹配点出发,依次经过非匹配边、匹配边、非匹配边…形成的路径叫交替路。 5、增广路:从一个未匹配点出发,走交替路,如果途径另一个未匹配点(出发的点不算),则这条交替 路称为增广路(agumenting path)。 6、匈牙利算法.

Annabel_CM的博客 1462

2024年电气工程师最新面试题及答案

1. **基本电气工程原理**:包括电流、电压、电阻、功率等基本概念。2. **欧姆定律**:V = IR,描述电压、电流和电阻之间的关系。42. **风力发电系统组成**:包括风力涡轮机、发电机、控制系统等。44. **智能电网技术**:包括自动化控制、通信技术、数据分析等。10. **减少EMI**:使用屏蔽、滤波、合理布线等方法。40. **光伏系统组成**:包括光伏板、逆变器、控制器等。48. **能量存储技术**:包括电池、超级电容器、飞轮等。

guo162308的博客 6565

DFS/BFS专练-搞定图论基础!(从海岛问题过渡至图论基础应用C/C++)

从海岛问题到图论基础:7 大经典场景 + N 个实战案例,彻底吃透 DFS/BFS 核心逻辑! 遇事不决,直接上纸,画图。

2302_80067378的博客 5653

1. 动手开发第一个 SAP CDS View

在开始学习前,大家需要根据这篇文章介绍的步骤,在自己本地电脑上,把 ABAP Development Tool 安装好。右键单击这个添加好的 ABAP 开发包,选择新建一个 ABAP Repository Object,类型就选择。,就可以像在 SAPGUI 里使用 SE16 那样,查看这个 CDS View 的内容。笔者下一篇文章,会详细介绍我们创建的第一个 CDS View 的每一行代码的详细含义。从本文开始,正式进入 CDS View 开发的学习。的条件,然后点击 Run 重新执行,得到结果。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1271

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

【算法】日期问题(C/C++)

日期问题见名知意,就是有关时间的问题,出题人在时间这一个角度去做文章,现在来看各大刷题网站,什么样的时间问题都有,比如闰年判断、回文日期、日期差值、日期格式化输入输出、时间轮询、时间窗口问题等。可所谓眼花缭乱,但是有的时间问题感觉就是图一乐,但是不排除创新题的可能性,后续也没有什么作用,既不会考也不会出在面试题上,下面我会对几种常见的日期问题进行详解。

闻道有先后,术业有专攻 7454

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

(图论)最短路问题合集(C++)

原题:思路:(依然是贪心的思想)1.初始化距离:dis[1]=0,dis[i]=INF(正无穷)2.循环n次:找到当前不在s中的dis最小的点(s表示已经确定最短距离的点(可以开一个st数组表示))假设找到了t这个点,用这个点更新其他所有点的最短距离:if dis[x]>dis[t]+wi(这里wi表示边权)实例演示:代码如下:一些注意细节(用//表示)这里储存方式用邻接矩阵,主要是因为用于稠密图。图中可能存在重边和自环,。

2302_79366101的博客 2051

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【算法】连通块问题(C/C++)

连通块问题(Connected Component Problem)是一个经典的图论问题,通常用来找出图中的所有连通分量。给定一个无向图,连通块问题的目标是确定图中有多少个连通分量(即有多少个互相连通的节点组成的集合)

闻道有先后,术业有专攻 8417

遗传算法解决TSP问题(C++)

很早做了综合实训,题目是用 遗传算法解决TSP问题。 今天写篇博客,一方面作为分享,另一方面作为知识回顾~ 为什么采用遗传算法解决问题呢?因为相比于其他普通算法,遗传算法有很大的优势,它摆脱了传统算法对问题参数的依赖,如连续、可导、可微等限制,只需对参数的编码进行操作,减少了求解问题的复杂性,同时它是一种全局搜索算法避免了陷入局部最优解。 本文章程序中,是求其TSP(38个城市)的近似解;去...

若水弹丸之地 3万+

C语言图论:最小生成树算法

本文系统讲解最小生成树问题的两种经典算法:Prim算法和Kruskal算法。Prim算法采用贪心策略,从顶点出发逐步扩张生成树,时间复杂度为O(|V|²);Kruskal算法通过排序边并利用并查集合并连通分量,时间复杂度主要取决于排序步骤。文章详细阐述了算法思想、实现步骤,并提供了完整的C语言代码实现,包括图的存储结构、并查集辅助数据结构等核心内容,帮助读者掌握最小生成树问题的解决方法。

2503_92860243的博客 1303

TSP问题的遗传算法实现(C++)

人工智能导论实验——TSP问题的遗传算法实现(C++)

qq_45907357的博客 7642
上一篇: 贪心区间类型题目的解法 (C++)
下一篇: linux用户管理
ghost_him
博客等级 码龄6年 598粉丝 90原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值