啊哈哈算法

1 桶排序

#include<iostream>
using namespace std;
int main() {
    int a[11], i, j, t;
    for (i = 0; i <= 10; i++) {
        a[i] = 0;//初始化为0
    }
    for (i = 1; i <= 5; i++) {
        cin >> t;
        a[t]++;
    }
    for (i = 0; i <= 10; i++) {
        for (j = 1; j <= a[i]; j++)
            cout << i<<" ";//i是数据 a[i]是记录几次的
    }
    return 0;
}

时间复杂度  O(M+N) M是桶的个数 N是待排序数的个数

2.冒泡排序

#include<iostream>
using namespace std;
void bubbleSort(int n,int arr[]) {
    for (int i = 1; i < n; i++){//n-1躺
        for (int j = 1; j <= n - i; j++) {//每次比较都会少一个
            if (arr[j] < arr[j + 1])
                swap(arr[j], arr[j + 1]);
        }
    }
}
int main() {
    int n;
    int arr[11];
    for (int i = 1; i <= 10; i++) {
        cin >> arr[i];
    }
    bubbleSort(10,arr);
    for (int i = 1; i <= 10; i++)
        cout << arr[i] << " ";
    return 0;
}

3.最常用的排序之 ——快速排序

#include<iostream>
using namespace std;
int a[101], n;
void quickSort(int left, int right) {
    if (left > right)return;
    int i = left;
    int j = right;
    while (i!= j) {
        while (a[j] >= a[left] && i < j)
            j--;
        while (a[i] <= a[left] && i < j)
            i++;
        if (i < j)
            swap(a[i], a[j]);
    }
    swap(a[i], a[left]);
    quickSort(left, i - 1);
    quickSort(i + 1, right);
    return;
}
int main() {
    int i, j, t;
    cin >> n;
    for (i = 1; i <= n; i++)
        cin >> a[i];
    quickSort(1, n);
    for (i = 1; i <= n; i++) {
        cout << a[i] << " ";
    }
    getchar();
    getchar();
    return 0;
}

第一章完结

第二章 栈  队列 链表
1.队列

#include<iostream>
using namespace std;
struct queue {
    int data[100];
    int head;
    int tail;
};
int main() {
    queue q;
    q.head = 1;
    q.tail = 1;
    for (int i = 1; i <= 9; i++) {
        cin >> q.data[q.tail];
        q.tail++;
    }
    while (q.head < q.tail) {
        cout << q.data[q.head];
        q.head++;
        q.data[q.tail] = q.data[q.head];
        q.tail++;
        q.head++;
    }
    return 0;
}

                                                                             万能的搜索 

1.深度优先搜索

#include<iostream>
using namespace std;
int a[10], book[10], n;
void dfs(int step) {
    int i;
    if (step == n + 1) {//如果站在第n+1个盒子面前,则表示前n个盒子已经放好扑克牌了
        //输出一种排列
        for (i = 1; i <= n; i++) {
            cout << a[i] << " ";
        }
        cout << endl;
    }
    return;
    //此时站在第step个盒子面前 应该放哪张牌呢
    //按照1,2,3···n的顺序一一尝试
    for (i = 1; i <= n; i++) {
        //判断扑克牌是否还在手上
        if (book[i] == 0) {
            a[step] = i;//将i号扑克牌放入到第step个盒子中
            book[i] = 1;//将book[i]设为1 表示i号扑克牌已经不在手上
            //第step个盒子已经放号扑克牌,接下来要走到下一个盒子面前
            dfs(step + 1);//这里通过递归调用来实现(自己调用自己)
            book[i] = 0;//这是非常重要的一步,一定要将刚才尝试的扑克牌收回,才能进行下一次尝试;
        }
    }
    return;
}
int main() {
    cin >> n;//输入的时候要注意n为1-9之间的整数
    dfs(1);//首先站在一号小盒子面前
    getchar();
    getchar();
    return 0;
}

//
void dfs(int step) {
    //判断边界
    //尝试每一种可能for(i=1;i<=n;i++)
     //继续下一步 step(step+1);

    //返回
}

#include<iostream>
using namespace std;
int a[10], book[10], total = 0;
void dfs(int step) {
    int i;
    if (step == 10) {
        if (a[1] * 100 + a[2] * 10 + a[3] + a[4] * 100 + a[5] * 10 + a[6] == a[7] * 100 + a[8] * 10 + a[9]) {
            total++;
            cout << a[1] << a[2] << a[3] << "+" << a[4] << a[5] << a[6] << "=" << a[7] << a[8] << a[9];
        }
        return;
    }
    for (i = 1; i <= 9; i++) {
        if (book[i] == 0) {
            a[step] = i;
            book[i] = 1;
            dfs(step + 1);
            book[i] = 0;
        }
    }
    return;
}
int main() {
    dfs(1);
    cout << "total=" << total / 2;
    getchar();
    getchar();
    return 0;
}

#include<iostream>
using namespace std;
int n, m, p, q, Min = 99999999;
int a[51][51], book[51][51];
void dfs(int x, int y, int step) {
    int next[4][2] = { {0,1},{1,0},{-1,0},{0,-1} };
    int tx, ty, k;
    if (x == p && y == q) {
        Min = min(Min, step);
        return;
    }
    //枚举四种走法
    for (k = 0; k <= 3; k++) {
        tx = x + next[k][0];
        ty = y + next[k][1];
        if (tx<1 || tx>n || ty<1 || ty>m)continue;
        if (a[tx][ty] == 0 && book[tx][ty] == 0) {
            book[tx][ty] = 1;//这个点已经走过
            dfs(tx, ty, step + 1);
            book[tx][ty] = 0;
        }
    }
    return;
}
int main() {
    int i, j, startx, starty;
    cin >> n >> m;
    //输入迷宫
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }
    //输入起点和终点
    cin >> startx >> starty >> p >> q;
    book[startx][starty] = 1;
    dfs(startx, starty, 0);
    cout << Min;
    getchar();
    getchar();
    return 0;
}

3.层层递进——广度优先搜索

#include<iostream>
using namespace std;
struct node {
    int x;//横坐标
    int y;//纵坐标
    int f;//父亲在队列中的编号 本题不要求输出路径,可以不要f
    int s;//步数
};
int main() {
    node que[2501];
    int a[51][51] = { 0 }, book[51][51] = { 0 };
    int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0}};
    int head, tail;
    int i, j, k, n, m, startx, starty, p, q, tx, ty, flag;
    cin >> n >> m;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            cin >> a[i][j];
        }
    }
    cin >> startx >> starty >> p >> q;
    head = 1;
    tail = 1;
    que[tail].x = startx;
    que[tail].y = starty;
    que[tail].f = 0;
    que[tail].s = 0;
    tail++;
    book[startx][starty] = 1;
    flag = 0;
    while (head < tail) {
        for (k = 0; k <= 3; k++) {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            if (tx<1 || tx>n || ty<1 || ty>m)continue;
            if (a[tx][ty] == 0 && book[tx][ty] == 0) {
                book[tx][ty] = 1;
                que[tail].x = tx;
                que[tail].y = ty;
                que[tail].f = head;
                que[tail].s = que[head].s + 1;
                tail++;
            }
            if (tx == p && ty == q) {
                flag = 1;
                break;
            }    
        }
        if (flag == 1)break;
        head++;
    }
    cout << que[tail - 1].s;
    return 0;
}

#include<iostream>
using namespace std;
struct node {
    int x;
    int y;
};
int main() {
    node que[2501];
    int head, tail;
    int a[51][51];
    int book[51][51] = { 0 };
    int i, j, k, sum, max = 0, mx, my, n, m, startx, starty, tx, ty;
    int next[4][2] = { {0,1},{1,0},{0,-1},{-1,0} };
    cin >> n >> m >> startx >> starty;
    //读入地图
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            cin >> a[i][j];
        }
    }
    //队列的初始化
    head = 1;
    tail = 1;
    que[tail].x = startx;
    que[tail].y = starty;
    tail++;
    book[startx][starty] = 1;
    sum = 1;
    //当队列不为空时
    while (head < tail) {
        //枚举四个方向
        for (k = 0; k <= 3; k++) {
            tx = que[head].x + next[k][0];
            ty = que[head].y + next[k][1];
            if (tx<1 || tx>n || ty<1 || ty>n)continue;
            if (a[tx][ty] > 0 && book[tx][ty] == 0) {
                sum++;
                book[tx][ty] = 1;
                que[tail].x = tx;
                que[tail].y = ty;
                tail++;
            }
        }
        head++;
    }
    cout << sum;
    return 0;
}

//多少个独立的小岛

#include<iostream>
using namespace std;
int a[51][51], book[51][51], n, m, sum;
void dfs(int x, int y, int color) {
    int next[4][2] = { {0,1},{1,0},{-1,0},{0,-1} };
    int k, tx, ty;
    a[x][y] = color;
    for (k = 0; k <= 3; k++) {
        tx = x + next[k][0];
        ty = y + next[k][1];
        if (tx<1 || tx>n || ty<1 || ty>m)continue;
        if (a[tx][ty] > 0 && book[tx][ty] == 0) {
            sum++;
            book[tx][ty] = 1;
            dfs(tx, ty, color);
        }
    }
    return;
}
int main() {
    int i, j, num = 0;
    cin >> n >> m;
    //读入地图
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            cin >> a[i][j];
        }
    }
    //对每一个大于0的点进行dfs染色
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            if (a[i][j] > 0) {
                num--;
                book[i][j] = 1;
                dfs(i, j, num);
            }
        }
    }
    //输出已经染色后的地图
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= m; j++) {
            cout << a[i][j] << " ";
        }
        cout << endl;
    }
    cout << "有" << -num << "个小岛";
    getchar();
    getchar();
    return 0;
}

                                                              图的遍历

图的存储 用二维数组 1表示有边 无穷大表示没有边 0表示是自己到自己 ——邻接矩阵存储法
 

1.深度优先搜索

使用深度优先搜索来遍历这个图的过程具体是:首先从一个未走到过的顶点作为起始顶点,比如以1号顶点作为起点。沿1号顶点的边去尝试访问其他未走到过的顶点,首先发现2号顶点还没走到过,于是来到了2号顶点。再以2号顶点作为出发点继续尝试访问其他未走到过的顶点。

#include<iostream>
using namespace std;
int e[101][101], book[101], n, m, sum;
void dfs(int cur) {
    cout << cur << " ";
    sum++;
    if (sum == n)return;
    for (int i = 1; i <= n; i++) {
        if (e[cur][i] == 1 && book[i] == 0) {
            book[i] = 1;
            dfs(i);
        }
    }
    return;
}
int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i == j)e[i][j] = 0;
            else e[i][j] = 99999999;
        }
    }
    for (int i = 1; i <= m; i++) {
        int a, b;
        cin >> a >> b;
        e[a][b] = 1;
        e[b][a] = 1;
    }
    book[1] = 1;
    dfs(1);
    getchar();
    getchar();
    return 0;
}
//5 5
// 1 2
//1 3
//1 5
//2 4
//3 5
//运行结果 1 2 3 4 5

2.广度优先遍历 首先以一个未被访问过的顶点作为起始顶点,访问其《所有》相邻的顶点,然后对每个相邻的顶点,再访问它们相邻的未被访问过的顶点,直到所有顶点都被访问过,遍历结束。

#include<iostream>
using namespace std;
int main() {
    int e[101][101], book[101] = { 0 }, i, j, n, m, a, b, cur;
    int que[10001], head, tail;
    head = 1;
    tail = 1;
    //初始化二维矩阵
    cin >> n >> m;
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j)e[i][j] = 0;
            else e[i][j] = 99999999;
        }
    }
    //读入顶点之间的边
    for (i = 1; i <= m; i++) {
        cin >> a >> b;
        e[a][b] = 1;
        e[b][a] = 1;
    }
    que[tail] = 1;
    tail++;
    book[1] = 1;
    while (head < tail) {
         cur = que[head];
        for (i = 1; i <= n; i++) {
            if (e[cur][i] == 1 && book[i] == 0) {
                book[i] = 1;
                que[tail] = i;
                tail++;
            }
            if (tail > n)break;
        }
        head++;
    }
    for (i = 1; i <= tail - 1; i++)
        cout << que[i] << " ";
    return 0;
}

城市地图 深度优先遍历

#include<iostream>
using namespace std;
int Min = 99999999, book[101], n, e[101][101];
void dfs(int cur, int dis) {
    int j;
    if (dis > Min)return;
    if (cur == n) {
        Min = min(Min, dis);
        return;
    }
    for (j = 1; j <= n; j++) {//1号城市到n号城市尝试
        if (e[cur][j] != 99999999 && book[j] == 0) {
            book[j] = 1;
            dfs(j, dis + e[cur][j]);
            book[j] = 0;
        }
    }
    return;
}
int main() {
    int i, j, m, a, b, c;
    cin >> n >> m;
    //初始化二维矩阵
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j)e[i][j] == 0;
            else e[i][j] = 99999999;
        }
    }
    //读入城市之间的道路
    for (i = 1; i <= m; i++) {
        cin >> a >> b >> c;
        e[a][b] = c;
    }
    //从1号城市出发
    book[1] = 1;
    dfs(1, 0);
    cout << Min;
    system("pause");
    return 0;
}

                                                                 最短路径

只有五行的代码——Floyd-Warshall 弗洛伊德算法

//经过1号顶点 两点之间的最短路径

for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            e[i][j] = min(e[i][j], e[i][1] + e[1][j]);
        }
    }

//经过2号顶点的情况下 任意两点之间的最短路径

for(i-1;i<=n;i++){

for(j=1;j<=n;j++){

e[i][j]=min(e[i][j],e[2][i]+e[i][j]);

}

}

//经过所有顶点作为中专站,任意两点最终的字段路程

for(k=1;k<=n;k++){

for(int i=1;i<=n;i++){

for(int j=1;j<=n;j++){

e[i][j]=min(e[i][j],e[i][k]+e[k][j]);

}

}

}

#include<iostream>
using namespace std;
int main() {
    int e[10][10], k, i, j, n, m, t1, t2, t3;
    int inf = 99999999;
    cin >> n >> m;
    //初始化
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j)e[i][j] = 0;
            else e[i][j] = inf;
        }
    }
    //读入边
    for (i = 1; i <= m; i++) {
        cin >> t1 >> t2 >> t3;
        e[t1][t2] = t3;
    }
    //算法的核心语句
    for (k = 1; k <= n; k++) {
        for (i = 1; i <= n; i++) {
            for (j = 1; j <= n; j++) {
                e[i][j] = min(e[i][j], e[i][k] + e[k][j]);
            }
        }
    }
    //输出最终的结果
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            cout << e[i][j] << " ";
        }
        cout << endl;
    }
    return 0;
}

迪杰斯特拉算法——通过边实现松弛  一个指定点到其余各个顶点的最短路径,也叫做单源最短路径  先找一个离指定点最近的顶点 然后这个顶点的值就确定了 然后拿这个顶点去缩短距离 重复此操作

与弗洛伊德算法一支 依然使用二维数组e来存储顶点之间边的关系

不能解决负权边的问题

#include<iostream>
using namespace std;
int main() {
    int e[10][10], dis[10], book[10], i, j, n, m, t1, t2, t3, u, v, min;
    int inf = 99999999;
    cin >> n >> m;
    //初始化
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j)e[i][j] = 0;
            else e[i][j] = inf;
        }
    }
    //读入边
    for (i = 1; i <= m; i++) {
        cin >> t1 >> t2 >> t3;
        e[t1][t2] = t3;
    }
    //初始化dis数组 ,这里是1号顶点到其余各个顶点的初始路程
    for (i = 1; i <= n; i++) {
        dis[i] = e[1][i];
    }
    //book数组的初始化
    for (i = 1; i <= n; i++) {
        book[i] = 0;
    }
    book[i] = 1;
    //迪杰斯特拉算法核心语句
    for (i = 1; i < n; i++) {
        //找离1号顶点最近的顶点
        min = inf;
        for (j = 1; j <= n; j++) {
            if (book[j] == 0 && dis[j] < min) {
                min = dis[j];
                u = j;
            }
        }
        book[u] = 1;
        for (v = 1; v <= n; v++) {
            if (e[u][v] < inf) {
                if (dis[v] > dis[u] + e[u][v])
                    dis[v] = dis[u] + e[u][v];
            }
        }
    }
    //输出最终的结果
    for (i = 1; i <= n; i++) {
        cout << dis[i] << " ";
    }
    getchar();
    getchar();
    return 0;
}

贝尔曼福特算法 解决单源最短路径 负权边问题

Bellman-Ford算法是一种单源最短路径算法,用于在有向图或负权边的图中计算一个节点到其他所有节点的最短路径。该算法采用了动态规划的思想,通过对边进行松弛操作来逐步缩小各个节点的距离。与Dijkstra算法不同的是,Bellman-Ford算法可以处理负权边,但会涉及到一个概念:负环,即每组连通的负权边构成的环路。

具体实现中,Bellman-Ford算法需要进行n-1轮松弛操作,其中n为节点数。对于每一条边(u, v, w),其中w表示u到v的边权值,在每一轮循环中,都要对节点v进行一次松弛操作,即更新v节点到每个邻居节点的距离。这样进行n-1轮之后,就能得到从起始节点s到每个节点的最短距离。如果在第n轮松弛操作中仍然发生了距离的更新,则说明存在负环,无法求解最短路径。

#include<iostream>
using namespace std;
int main() {
    int dis[10], i, k, n, m, u[10], v[10], w[10];
    int inf = 99999999;
    cin >> n >> m;
    //读入边
    for (i = 1; i <= m; i++) {
        cin >> u[i] >> v[i] >> w[i];
    }
    //初始化dis数组 ,这里是1号顶点到其余各个顶点的初始路程
    for (i = 1; i <= n; i++) {
        dis[i] = inf;
    }
    dis[1] = 0;
    //贝尔曼 福特算法的核心
    for (k = 1; k < n - 1; k++) {
        for (i = 1; i <= m; i++) {
            if (dis[v[i]] > dis[u[i]] + w[i])
                dis[v[i]] = dis[u[i]] + w[i];

        }
    }
    //输出最终结果
    for (i = 1; i <= n; i++)
        cout << dis[i] << " ";
    return 0;
}

升级

#include<iostream>
using namespace std;
int main() {
    int dis[10], bak[10], i, k, n, m, u[10], v[10], w[10], check, flag;
    int inf = 99999999;
    cin >> n >> m;
    //读入边
    for (i = 1; i <= m; i++) {
        cin >> u[i] >> v[i] >> w[i];
    }
    //初始化dis数组,这里是1号顶点到其余各个顶点的初始路程
    for (i = 1; i <= n; i++) {
        dis[i] = inf;
    }
    dis[1] = 0;
    //贝尔曼福特算法的核心
    for (k = 1; k < n; k++) {
        //将dis数组备份到bak数组中
        for (i = 1; i <= n; i++) {
            //进行一轮松弛
            if (dis[v[i]] > dis[u[i]] + w[i]);
            dis[v[i]] = dis[u[i]] + w[i];
        }
        check = 0;
        for (i = 1; i <= n; i++)if (bak[i] != dis[i]) {
            check = 1;
            break;
        }
        if (check == 0)break;
    }
    //检测负权回路
    flag = 0;
    for (i = 1; i <= m; i++) {
        if (dis[v[i]] > dis[u[i]] + w[i])flag = 1;
    }
    if (flag == 1)cout << "此图含有父权回路";
    else {
        for (i = 1; i <= n; i++)
            cout << dis[i] << " ";
    }
    return 0;
}

#include<iostream>
using namespace std;
int n;
int h[100];
//向下调整的代码如下
void siftdown(int i) {
    int t;
    //当节点i有儿子 并且需要向下调整的时候 循环就执行
    while (i * 2 <= n) {
        //首先判断它和左儿子的关系
        if (h[i] > h[i * 2])
            t = i * 2;
        else
            t = i;
        //如果它有右儿子在对右儿子进行讨论
        if (i * 2 + 1 <= n) {
            if (h[t] > h[t * 2 + 1])
                t = i * 2 + 1;
        }
        if (t != i) {
            swap(h[i], h[t]);
            i = t;
        }
        else
            break;
    }

}
//向上调整的代码如下
void siftup(int i) {//传入一个需要调整的代码
    int flag = 0;
    if (i == 1)return;//如果是堆顶就直接返回了
    while (i != 1) {
        if (h[i] < h[i / 2]) {
            i /= 2;
            swap(h[i], h[i / 2]);
        }
        else break;    
    }
}


//向上调整的代码如下
void siftup(int i) {//传入一个需要调整的代码
    int flag = 0;
    if (i == 1)return;//如果是堆顶就直接返回了
    while (i != 1) {
        if (h[i] < h[i / 2]) {
            swap(h[i], h[i / 2]);
        }
        else break;
        i /= 2;
    }
}
int main() {
    return 0;
}

                                                                    树

把n个元素建立一个堆 首先我们可以将这n个节点以自顶向下 从左到右从1到n编码,这样

我们就可以把这n个节点转换成为一个完全二叉树 如何从最后一个非叶节点n/2开始到根节点 向下调整

for (int i = n / 2; i >= 1; i--)
        siftdown(i);
    

//删除最大的元素

int delete(){

int t ;

t=h[1];

h[1]=h[n];

n--;

siftdown(1);

return t;

}

#include<iostream>
using namespace std;
int n, h[101];
void siftdown(int i) {
    int t;
    while (i * 2 <= n) {
        if (h[i] < h[i * 2])
            t = i * 2;
        else
            t = i;
        if (i * 2 + 1 <= n && h[t] < h[i * 2 + 1])
            t = i * 2 + 1;
        if (t != i) {
            swap(h[t], h[i]);
            i = t;//这里别忘记了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊
        }
        else break;
    }
}
void create() {
    for (int i = n / 2; i >= 1; i--)
        siftdown(i);
}
void heapSort() {
    while (n >= 1) {
        swap(h[1], h[n]);
        n--;
        siftdown(1);
    }
}
int main() {
    cin >> n;
    int t;
    t = n;
    for (int i = 1; i <= n; i++)
        cin >> h[i];
    create();
    heapSort();
    for (int i = 1; i <= t; i++)
        cout << h[i] << " ";
    return 0;
}

查并集

查并集算法(Union-Find算法)是一种用于处理不相交集合(Disjoint Set)的数据结构。这种数据结构支持两个主要操作:合并(Union)和查找(Find)。

初始时,每个元素(或节点)都视为一个独立的集合。Union操作将两个集合合并为一个集合,而Find操作可以用于识别两个元素是否属于同一集合。在实际应用中,查并集算法通常用于连通性问题,比如判断图中两个节点是否连通,或者计算连通分量的个数。

查并集算法的具体实现有多种方法,其中最常见的是Quick Find算法、Quick Union算法和Weighted Quick Union算法。这些算法的时间复杂度不同,但都保证了基本操作(Union和Find)的平均时间复杂度为常数级别。

总之,查并集算法提供了一种有效地管理集合的方法,并且可以在很多实际应用中发挥重要作用。

#include<iostream>
using namespace std;
int f[1000] = { 0 }, n, m, k, sum = 0;
void init() {
    for (int i = 1; i <= n; i++) {
        f[i] = i;
    }
}
int getf(int v) {
    if (f[v] == v)
        return v;
    return f[v] = getf(f[v]);
}
void merge(int v, int u) {
    int t1, t2;
    t1 = getf(v);
    t2 = getf(u);
    if (t1 != t2) {
        f[t2] = t1;
    }
}
int main() {
    int i, x, y;
    cin >> n >> m;
    //初始化
    init();
    for (i = 1; i <= m; i++) {
        //开始合并犯罪团伙
        cin >> x >> y;
        merge(x, y);
    }
    //最后扫描有多少个独立的犯罪团伙
    for (i = 1; i <= n; i++) {
        if (f[i] == i)
            sum++;
    }
    cout << sum;
    system("pause");
    return 0;
}

     图的最小生成树

#include<iostream>
using namespace std;
struct edge {
    int u;
    int v;
    int w;
};
edge e[10];//注意!!!大小要比边的数量大1 
int n, m;
int f[7], sum, Count;//f数组的大小要比n的大小大1 
void quickSort(int left, int right) {
    if (left > right)return;
    int i = left;
    int j = right;
    while (i != j) {
        while (e[j].w >= e[left].w && i < j)j--;
        while (e[i].w <= e[left].w && i < j)i++;
        if (i < j)swap(e[i], e[j]);
    }
    if (i < j) {//这个判断条件别忘了啊啊啊啊啊啊啊啊啊啊啊!!!!!!!
        swap(e[i], e[left]);
    }
    swap(e[i], e[left]);
    quickSort(left, i - 1);
    quickSort(i + 1, right);
    return;
}
int getf(int v) {
    if (f[v] == v)return v;
    return f[v] = getf(f[v]);
}
int merge(int v, int u) {
    int t1 = getf(v);
    int t2 = getf(u);
    if (t1 != t2) {
        f[t2] = t1;
        return 1;
    }
    return 0;
}
int main() {
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        cin >> e[i].u >> e[i].v >> e[i].w;
    }
    quickSort(1, m);
    //库鲁斯卡尔算法的核心
    for (int i = 1; i <= n; i++) {
        f[i] = i;
    }
    for (int i = 1; i <= m; i++) {
        if (merge(e[i].v, e[i].u)) {
            Count++;
            sum += e[i].w;
        }
        //结束条件也别忘了啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊!!!
        if (Count == n - 1)break;
    }
    cout << sum << " " << Count;
    return 0;
}

#include<iostream>
using namespace std;
int main() {
    int n, m, i, j, k, Min, t1, t2, t3;
    int e[7][7], dis[7], book[7] = { 0 };//这里对book数组进行了初始化
    int inf = 99999999;
    int count = 0, sum = 0;
    //读入n和m n表示顶点的个数 m表示表示边的个数
    cin >> n >> m;
    //初始化
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j)e[i][j] = 0;
            else e[i][j] = inf;
        }
    }

    //开始读入边
    for (i = 1; i <= m; i++) {
        cin >> t1 >> t2 >> t3;
        e[t1][t2] = t3;
        e[t2][t1] = t3;
    }

    //初始化dis数组 这里是1号顶点到各个顶点的初始化的距离 因为当前生成树中只有1号顶点
    for (i = 1; i <= n; i++) {
        dis[i] = e[1][i];
    }

    //prim核心开始
    //将1号顶点加入生成树
    book[1] = 1;
    count++;
    while (count < n) {
        Min = inf;
        for (i = 1; i <= n; i++) {
            if (book[i] == 0 && dis[i] < Min) {
                Min = dis[i];
                j = i;
            }
        }
        count++;
        sum += dis[j];
        //扫描当前顶点j所有的边 再以j为中间点 更新生成树到每一个非树顶点的距离
        for (k = 1; k <= n; k++) {
            if (book[k] == 0 && dis[k] > e[j][k])
                dis[k] = e[j][k];
        }
    }
    cout << sum;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值