图论(基础)

知识:

顶点,边 | 权,度数

1.图的种类:

有向图 | 无向图

有环 | 无环

联通性

基础1:图的存储(主要是邻接矩阵和邻接表)

例一:B3643 图的存储 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>

using namespace std;

int n, m, d[1010];
bool edges[1010][1010];

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

    for(int i = 1; i <= m; i ++ )
    {
        int u, v;
        cin >> u >> v;
        
        edges[u][v] = true;
        edges[v][u] = true;
    }
    for(int i = 1; i <= n; i ++ )
    {
        for(int j = 1; j <= n; j ++ )
        {
            if(edges[i][j]) 
            {
                cout << "1 ";
                d[i] ++;
            }
            else cout << "0 "; 
        }
        cout << endl;
    }
  
    for(int i = 1; i <= n; i ++ )
    {
        cout << d[i] << ' ';
        for(int j = 1; j <= n; j ++ )
        {
            if(edges[i][j]) cout << j << ' ';
        }
        cout << endl;
    }
    return 0;
}

例二:B3613 图的存储与出边的排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

该代码须加上快读快写

#include <iostream>
#include <set>
using namespace std;

const int N = 5e5 + 10;
int n, m;
set<int> s[N];

int main()
{
    int t;
    cin >> t;
    
    while(t -- )
    {
        cin >> n >> m;
        
        for(int i = 0; i < m; i ++ )
        {
            int a, b;
            cin >> a >> b;
            s[a].insert(b);
        }
        
        int j = 0;
        for(int i = 1; i <= n; i ++ )
        {
            for(auto it = s[i].begin(); it != s[i].end(); it ++ )
                cout << *it << ' ';
            cout << endl;
        }
        
    }
    
    return 0;
}

图的遍历:通常是bfs()、dfs()

复习一下模板活动 - AcWing 活动 - AcWing

例一:P3916 图的遍历 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

因为是找最大值dfs,用了反向建边提高效率,用一个大值去标记多个小值

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

const int N = 1e5 + 10, M = 2 * N;
int n, m;
int e[N], ne[N], h[N], idx;
int res[N];

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

void dfs(int u, int maxn)
{
    res[u] = max(maxn, res[u]);
    
    for(int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        if(!res[j]) dfs(j, maxn);
    }
}

int main()
{
    cin >> n >> m;
    
    memset(h, -1, sizeof h);
    while(m -- )
    {
        int u, v;
        cin >> u >> v;
        
        add(v, u);
    }
    
    for(int i = n; i >= 1; i -- )
    {
        //反向建边+遍历 有利于找最大值的效率
        // 如果是第一次被遍历到一定找到了遍历最大的值
        //已经被标记过最大值的说明他们下边的最大值也被标记过了
        if(res[i]) continue;
        dfs(i, i);
    }
    for(int i = 1; i <= n; i ++ )
    {
        cout << res[i] << ' ';
    }
    return 0;
}

例二:活动 - AcWing 图的层次

肯定要用bfs啦

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

const int N = 1e5 + 10;
int h[N], e[N], ne[N], idx;
int d[N];
int n,m;
queue<int> q;

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

int bfs()
{
    memset(d, -1, sizeof d);
    d[1] = 0;
    q.push(1);
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        for(int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if(d[j] == -1)
            {
                d[j] = d[t] + 1;
                q.push(j);
            }
        }
    }
    
    return d[n];
}

int main(){
    cin >> n >> m;
    
    memset(h, -1, sizeof h);
    
    for(int i = 0; i < m; i++ )
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
    }
    
    cout << bfs() << endl;
    
    return 0;
}

例三:P5318 【深基18.例3】查找文献 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

分别用dfs和bfs输出一遍。唯一的难点在于怎么做到 "如果有很多篇文章可以参阅,请先看编号较小的那篇(因此你可能需要先排序)。" 问题不大,排个序就行。

注意用邻接表存图(s存边先处理一下,即排序) 然后处理e[i][]表示i点连接的点

然后就是喜闻乐见的dfs递归一下,bfs一下

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;

const int N = 1e5 + 10;
struct edges
{
    int a, b;
};
vector<int> e[N]; // e是邻接表,用来遍历
vector<edges> s; // 用来存边
int n, m;
bool st1[N], st2[N];
queue<int> q;

bool cmp(edges x, edges y)
{
    //按照每条边终点从小到大排,终点相同的起点按从小到大排
    if(x.b == y.b) 
        return x.a < y.a;
    else 
        return x.b < y.b;
}

void bfs()
{
    q.push(1);
    st2[1] = true;
    cout << '1' << ' ';
    
    while(q.size())
    {
        int t = q.front();
        q.pop();
        
        for(int i = 0; i < e[t].size(); i ++ )
        {
            int j = s[e[t][i]].b;
            if(!st2[j])
            {
                st2[j] = true;
                cout << j << ' ';
                q.push(j);
            }
            
        }
    }
}
void dfs(int u)
{
    st1[u] = true;
    cout << u << ' ';
    
    for(int i = 0; i < e[u].size(); i ++ )
    {
        int j = s[e[u][i]].b;
        if(!st1[j]) dfs(j);
    }
}

int main()
{
    cin >> n >> m;
    
    for(int i = 0; i < m; i ++ )
    {
        int a, b;
        cin >> a >> b;
        
        s.push_back((edges){a, b});
    }
    
    sort(s.begin(), s.end(), cmp);
    
    //m条边放到e中 
    for(int i = 0; i < m; i ++ )
    {
        e[s[i].a].push_back(i); // e存某个点到其他点的边的编号
    }
    
    // for(int i = 0; i < m; i ++ )
    // {
    //     cout << s[i].a << ':' << s[i].b << endl;
    // }
    dfs(1);
    puts("");
    bfs();
    return 0;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于高精度存储结构的选择排序的 C 语言代码实现: ```c #include <stdio.h> #include <string.h> // 高精度整数结构体 typedef struct { int num[1000]; // 数组存储每位数字 int len; // 整数长度 } BigInt; // 初始化高精度整数 void init(BigInt *a) { memset(a->num, 0, sizeof(a->num)); a->len = 0; } // 高精度整数赋值 void assign(BigInt *a, char *s) { int i, j; init(a); a->len = strlen(s); for (i = 0, j = a->len - 1; i < a->len; i++, j--) { a->num[i] = s[j] - '0'; } } // 高精度整数比较大小 int cmp(BigInt a, BigInt b) { int i; if (a.len != b.len) { return a.len - b.len; } for (i = a.len - 1; i >= 0; i--) { if (a.num[i] != b.num[i]) { return a.num[i] - b.num[i]; } } return 0; } // 高精度整数交换 void swap(BigInt *a, BigInt *b) { BigInt tmp; memcpy(&tmp, a, sizeof(BigInt)); memcpy(a, b, sizeof(BigInt)); memcpy(b, &tmp, sizeof(BigInt)); } // 高精度整数选择排序 void selectionSort(BigInt arr[], int n) { int i, j, min_idx; for (i = 0; i < n - 1; i++) { min_idx = i; for (j = i + 1; j < n; j++) { if (cmp(arr[j], arr[min_idx]) < 0) { min_idx = j; } } if (min_idx != i) { swap(&arr[i], &arr[min_idx]); } } } // 打印高精度整数 void printBigInt(BigInt a) { int i; for (i = a.len - 1; i >= 0; i--) { printf("%d", a.num[i]); } printf("\n"); } int main() { int n, i; char s[1000]; BigInt arr[1000]; printf("输入整数个数:"); scanf("%d", &n); for (i = 0; i < n; i++) { printf("输入第 %d 个整数:", i + 1); scanf("%s", s); assign(&arr[i], s); } selectionSort(arr, n); printf("排序结果:\n"); for (i = 0; i < n; i++) { printf("%d: ", i + 1); printBigInt(arr[i]); } return 0; } ``` 在以上代码中,使用了一个 `BigInt` 结构体来存储高精度整数。该结构体包含一个 `num` 数组来存储每位数字,以及一个 `len` 变量来存储整数的长度。在初始化、赋值、比较大小、交换、打印高精度整数等操作时,都需要对 `num` 数组和 `len` 变量进行相应的处理。 选择排序的实现与普通的选择排序类似,只需要根据比较函数 `cmp` 来比较两个高精度整数的大小,并在交换时调用 `swap` 函数即可。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值