C++ 图论小代码

        导言

//24.07.20 新生训练

——//感谢万能的学长

//注:本篇所用代码中,一部分为核心代码,非完整代码,读者使用时务必完善

        最短路径

                        Floyd算法小代码(核心)
int g[N][N];

void solve()
{
    memset(g, inf, sizeof g); // 默认是无穷大,inf=0x3f3f3f3f
    cin >> n >> m;
    int u, v, w;
    for (int i = 1; i <= m; ++i)
    {
        g[i][i] = 0; // 自己到自己的距离是0
        cin >> u >> v >> w;
        g[u][v] = g[v][u] = w;
    }

    for (int k = 1; k <= n; ++k) // 枚举中间经过的节点
    {
        for (int i = 1; i <= n; ++i) // 枚举出发点
        {
            for (int j = 1; j <= n; ++j) // 枚举终点
            {
                if (g[i][k] + g[k][j] < g[i][j])
                {
                    g[i][j] = g[i][k] + g[k][j];
                }
            }
        }
    }

    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= n; ++j)
        {
            cout << g[i][j] << ' ';
        }
        cout << '\n';
    } // 每个点到每个点的最短路的矩阵
}

                        Dijkstra算法小代码
                1. n * n 的Dijkstra(Acwing)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;

const int N = 550;
int g[N][N];
int d[N];
bool st[N];
int n, m;

int dijkstra()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;

    for (int i = 0; i < n; i++)
    {
        int t = -1;
        for (int j = 1; j <= n; j++) // 距离当前最近的那个节点
        {
            if (!st[j] && (t == -1 || d[j] < d[t]))
            {
                t = j;
            }
        }

        st[t] = 1;

        for (int j = 1; j <= n; j++)
        {
            d[j] == min(d[j], d[t] + g[t][j]);
        }
    }
    if (d[n] == 0x3f3f3f3f)
        return -1;
    else
        return d[n];
}

int main()
{
    cin >> n >> m;
    memset(g, 0x3f, sizeof g);
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u][v] = min(g[u][v], w);
    }
    int t = dijkstra();
    cout << t << "\n";
}

                2.(n + m)log(n) 的 dijkstra(Acwing)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 2e5 + 10;
typedef pair<int, int> PII;
vector<PII> g[N];

int d[N];
bool st[N];
int n, m;
// n*n
int dijkstra() // (n+m)log(n);
{
    memset(d, 0x3f, sizeof d);
    priority_queue<PII, vector<PII>, greater<PII>> q; //{当前点的距离,当前点是谁};
    d[1] = 0;
    q.push({0, 1});
    while (q.size())
    {
        auto t = q.top();
        q.pop();
        int x = t.first, y = t.second;

        if (st[y])
            continue;
        st[y] = 1;
        // y: 由y进行更新所有邻边
        // g[y].push_back({u,w});
        for (int i = 0; i < g[y].size(); i++)
        {
            int u = g[y][i].first;
            int w = g[y][i].second;
            // 0x3f3f3f3f
            if (d[u] > d[y] + w)
            {
                d[u] = d[y] + w;
                q.push({d[u], u});
            }
        }
    }
    if (d[n] == 0x3f3f3f3f)
        return -1;
    else
        return d[n];
}
int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
       cin >> u >> v >> w;
       g[u].push_back({v,w}); // { , } 
    }
    int t=dijkstra();
    cout << t << "\n";
}

                        Bellman-Ford算法小代码(Acwing)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <bits/stdc++.h>

using namespace std;

const int N = 550;
const int M = 1e4 + 10;

struct node
{
    int x, y, w;
} e[M];

int n, m, k;
int d[N], la[N];

void BF()
{
    memset(d, 0x3f, sizeof d);
    d[1] = 0;
    int d[N], la[N];
    for (int i = 0; i < k; i++)
    {
        memcpy(la, d, sizeof d); // 防止明明 k次到不了的点,却还被更新了
        for (int j = 0; j < m; j++)
        {
            int a = e[j].x, b = e[j].y, c = e[j].w;
            d[b] = min(d[b], la[a] + c);
        }
    }
    if (d[n] > 0x3f3f3f3f / 2)
        cout << "impossible\n";
    else
        cout << d[n] << "\n";
}

int main()
{
    cin >> n >> m >> k;

    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        e[i] = {a, b, c};
    }

    BF();
    return 0;
}

                        SPFA算法小代码(Acwing)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int N = 1e5 + 10;
typedef pair<int, int> PII;
vector<PII> g[N];

int n, m;
int d[N], cnt[N];
bool st[N];
int spfa()
{
    memset(d, 0x3f, sizeof d);
    queue<int> q;
    d[1] = 0;
    q.push(1);
    st[1] = true;
    while (q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        // t
        for (int i = 0; i < g[t].size(); i++)
        {
            int a = g[t][i].first, b = g[t][i].second;
            if (d[a] > d[t] + b)
            {
                d[a] = d[t] + b;
                cnt[a] = cnt[t] + 1;

                if (cnt[a] >= n)
                    return false;
                if (!st[a])
                {
                    q.push(a);
                    st[a] = true;
                }
            }
        }
    }
    return true;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a].push_back({b, c});
    }
    int t = spfa();
    if (t == 0x3f3f3f3f)
        cout << "impossible\n";
    else
        cout << t << "\n";
}

                        SPFA判断负环(Acwing)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int N = 1e5 + 10;
typedef pair<int, int> PII;
vector<PII> g[N];

int n, m;
int d[N], cnt[N];
bool st[N];
int spfa()
{
    queue<int> q;
    for (int i = 1; i <= n; i++)
    {
        q.push(i);
        st[i] = true;
    }
    while (q.size())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        // t
        for (int i = 0; i < g[t].size(); i++)
        {
            int a = g[t][i].first, b = g[t][i].second;
            if (d[a] > d[t] + b)
            {
                d[a] = d[t] + b;
                cnt[a] = cnt[t] + 1;

                if (cnt[a] >= n)
                    return false;
                if (!st[a])
                {
                    q.push(a);
                    st[a] = true;
                }
            }
        }
    }
    return true;
}

int main()
{
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a].push_back({b, c});
    }
    int t = spfa();
    if (t == 0x3f3f3f3f)
        cout << "impossible\n";
    else
        cout << t << "\n";
}

         图的存储结构

                        邻接表(vector实现)存图,dfs与bfs(核心)
int n,m;
LL k;

vector<PII>g[N];
bool vis[N];

void dfs(int u){
    vis[u]=1;
    cout<<u<<' ';
    for(auto &j:g[u]){
        int w=j.first,v=j.second;
        if(!vis[v]){
            dfs(v);
        }
    }
}

void bfs(int st){
    memset(vis,0,sizeof vis);
    queue<int>q;
    q.push(st);
    vis[st]=1;
    while(!q.empty()){
        int u=q.front();
        cout<<u<<' ';
        q.pop();
        for(auto &j:g[u]){
            int w=j.first,v=j.second;
            if(vis[v])continue;
            vis[v]=1;
            q.push(v);
        }
    }
}

void solve(){
    cin>>n>>m;
    int u,v,w;
    for(int i=1;i<=m;++i){
        cin>>u>>v>>w;
        g[u].push_back({w,v});
        g[v].push_back({w,u});
    }
    dfs(1);
    cout<<'\n';
    bfs(1);
}

                        链式前向星(核心)
int n,m;
LL k;

int head[N],to[N],w[N],ne[N],idx;

void add(int a,int b,int c){//每条边按输入顺序编号
    to[idx]=b;//这条边到达的点
    w[idx]=c;//这条边的权
    ne[idx]=head[a];//最新的边的在链表中的下一个节点为链表当前的头节点
    head[a]=idx;//最新的边作为链表的头节点
    idx++;
}

bool vis[N];

void dfs(int u){
    vis[u]=1;
    cout<<u<<' ';
    for(int i=head[u];~i;i=ne[i]){
        int v=to[i];
        if(!vis[v]){
            dfs(v);
        }
    }
}

void bfs(int st){
    memset(vis,0,sizeof vis);
    queue<int>q;
    q.push(st);
    vis[st]=1;
    while(!q.empty()){
        int u=q.front();
        cout<<u<<' ';
        q.pop();
        for(int i=head[u];~i;i=ne[i]){
            int v=to[i];
            if(vis[v])continue;
            vis[v]=1;
            q.push(v);
        }
    }
}

        最小生成树

                        Prim算法小代码(Acwing)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <bits/stdc++.h>

using namespace std;
const int N = 550;
int g[N][N];
bool st[N];
int d[N];
int n, m;
void init()
{
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= n; j++)
        {
            if (i == j)
                g[i][j] = 0;
            else
                g[i][j] = 0x3f3f3f3f;
        }
    }
}

int prim()
{
    int ans = 0;
    memset(d, 0x3f, sizeof d);
    for (int i = 0; i < n; i++)
    {
        int t = -1;
        for (int j = 1; j <= n; j++)
        {
            if (!st[j] && (t == -1 || d[j] < d[t]))
                t = j;
        }

        if (i > 0 && d[t] == 0x3f3f3f3f)
        {
            return -0x3f3f3f3f;
        }
        if (i > 0)
            ans += d[t];
        st[t] = true;
        for (int j = 1; j <= n; j++)
        {
            d[j] = min(d[j], g[t][j]);
        }
    }
    return ans;
}

int main()
{
    cin >> n >> m;
    init();
    for (int i = 0; i < m; i++)
    {
        int u, v, w;
        cin >> u >> v >> w;
        g[u][v] = g[v][u] = min(g[u][v], w);
    }

    int t = prim();
    if (t == -0x3f3f3f3f)
    {
        cout << "impossible\n";
    }
    else
        cout << t << "\n";
    return 0;
}

                         Kruskal算法小代码(Acwing)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <bits/stdc++.h>

using namespace std;
const int N = 1e5 + 10;

int p[N];

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

struct node
{
    int x, y, w;
    bool operator<(const node &Z) const
    {
        return w < Z.w;
    }
} e[N];

bool cmp(node &X, node &Y)
{
    return X.w < Y.w;
}
int n, m;
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        p[i] = i;
    }
    for (int i = 0; i < m; i++)
    {
        cin >> e[i].x >> e[i].y >> e[i].w;
    }
    sort(e, e + m);
    int cnt = 0, ans = 0;
    for (int i = 0; i < m; i++)
    {
        int x = e[i].x, y = e[i].y, w = e[i].w;
        int a = find(x), b = find(y);

        if (a != b)
        {
            cnt++;
            p[a] = b;
            ans += w;
        }
    }
    if (cnt != n - 1)
    {
        cout << "impossible\n";
    }
    else
        cout << ans << "\n";
    return 0;
}

         拓扑排序

                        核心
int n,m;
LL k;

vector<int>g[N];
int in[N];

void toposort(){
    queue<int>q;
    for(int i=1;i<=n;++i){
        if(!in[i]){
            q.push(i);//入度为0的点进入队列
        }
    }

    while(!q.empty()){
        int u=q.front();
        cout<<u<<' ';
        q.pop();//弹出入队为0的点
        for(auto &v:g[u]){
            --in[v];//删除连接到节点v的边(入度减一)
            if(!in[v]){
                q.push(v);//入度为0,入队
            }
        }
    }
}

void solve(){
    cin>>n>>m;
    int u,v,w;
    for(int i=1;i<=m;++i){
        cin>>u>>v;
        g[u].push_back(v);
        ++in[v];//记录每个点的入度
    }
    toposort();
}

//笔者打了好几天,终于完工了 hwh

//这些大概就是C++图论的一些小代码了吧~

~~~仅当笔者个人备忘录使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值