蓝桥杯第十二讲--图论【习题】(二)

简介: 蓝桥杯第十二讲--图论【习题】

单链表

题目要求

题目描述:

实现一个单链表,链表初始为空,支持三种操作:

  1. 向链表头插入一个数;
  2. 删除第 k 个插入的数后面的数;
  3. 在第 k个插入的数后插入一个数。


现在要对该链表进行 M次操作,进行完所有操作后,从头到尾输出整个链表。

注意: 题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n  个数依次为:第 1  个插入的数,第 2 个插入的数,…第 n 个插入的数。

输入格式:

image.png

输出格式:

共一行,将整个链表从头到尾输出。

数据范围:

1M100000

所有操作保证合法。

输入样例:

10
H 9
I 1 1
D 1
D 0
H 6
I 3 6
I 4 5
I 4 5
I 3 4
D 6

输出样例:

6 4 6 5

思路分析

模板类题目,对插入和删除操作必须做到能够快速打出代码的程度。

代码

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010;
int head, idx;
int e[N], ne[N];
void add_head(int x)
{
    e[idx] = x, ne[idx] = head, head = idx ++;
}
void remove(int k)
{
    ne[k] = ne[ne[k]];
}
void add_k(int k, int x)
{
    e[idx] = x, ne[idx] = ne[k], ne[k] = idx ++;
}
int main()
{
    head = -1;
    int m;
    scanf("%d", &m);
    while (m -- )
    {
        char op[2];
        scanf("%s", op);
        if (op[0] == 'H') 
        {
            int x;
            scanf("%d", &x);
            add_head(x);
        }
        else if (op[0] == 'D')
        {
            int k;
            scanf("%d", &k);
            if (!k) head = ne[head];
            else remove(k - 1);
        }
        else
        {
            int k, x;
            scanf("%d%d", &k, &x);
            add_k(k - 1, x);
        }
    }
    for (int i = head; ~i; i = ne[i]) printf("%d ", e[i]);
    return 0;
}

大臣的旅费

题目要求

题目描述:

image.png

输入格式:

image.png

输出格式:

输出一个整数,表示大臣 J 最多花费的路费是多少。

数据范围:

image.png

输入样例:

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

输出样例:

135

思路分析

image.png

结论推导:(感兴趣的可以看看)

image.png

image.png

image.png

image.png

🌞🌞🌞综上所述,(2 3 ) 是直径。

代码 (vector存储的dfs

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 100010;
struct Edge
{
    int id, w;
};
int n;
vector<Edge>v[N];
int dist[N];
void dfs(int u, int father, int distance)
{
    dist[u] = distance;
    for (auto t : v[u])
        if (t.id != father)
            dfs(t.id, u, dist[u] + t.w);
}
int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i ++ ) 
    {
        int p, q, d;
        scanf("%d%d%d", &p, &q, &d);
        v[p].push_back({q, d});
        v[q].push_back({p, d});
    }
    dfs(1, -1, 0);
    int u = 1;
    for (int i = 1; i <= n; i ++ )
        if (dist[u] < dist[i])
            u = i;
    dfs(u, -1, 0);
    for (int i = 1; i <= n; i ++ )
        if (dist[u] < dist[i])
            u = i;
    int s = dist[u];   // s 就是树的直径
    printf("%lld\n", (1ll + s) * s / 2 + s * 10);
    return 0;
}

代码 (链表存储的dfs)

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 100010;
int n;
int h[N], e[2 * N], w[2 * N], ne[2 * N], idx;
int dist[N];
void add(int p, int q, int d)
{
    e[idx] = q, w[idx] = d, ne[idx] = h[p], h[p] = idx ++;
}
void dfs(int u, int father, int distance)
{
    dist[u] = distance;
    for (int i = h[u]; ~i; i = ne[i])
    {
        int j = e[i];
        if (j != father)
            dfs(j, u, distance + w[i]);
    }
}
int main()
{
    memset(h, -1, sizeof h);
    scanf("%d", &n);
    for (int i = 0; i < n; i ++ )
    {
        int p, q, d;
        scanf("%d%d%d", &p, &q, &d);
        add(p, q, d);
        add(q, p, d);
    }
    int u = 1;
    dfs(1, -1, 0);
    for (int i = 1; i <= n; i ++ ) 
        if (dist[u] < dist[i])
            u = i;
    dfs(u, -1, 0);
    for (int i = 1; i <= n; i ++ ) 
        if (dist[u] < dist[i])
            u = i;
    int s = dist[u];
    printf("%lld\n", s * 10 + (1ll + s) * s / 2);
    return 0;
}

代码 (链表存储的bfs)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int N = 100010;
int n;
int idx, h[N], e[2 * N], ne[2 * N], w[2 * N];
int dist[N];
queue<int> q;
void add(int p, int q, int d)
{
    e[idx] = q, w[idx] = d, ne[idx] = h[p], h[p] = idx ++;
}
void bfs(int u)
{
    q.push(u);
    dist[u] = 0;
    while (q.size())
    {
        auto t = q.front();
        q.pop();
        for (int i = h[t]; ~i; i = ne[i] )
        {
            int j = e[i];
            if (dist[j] != -1) continue;
            dist[j] = dist[t] + w[i];
            q.push(j);
        }
    }
}
int main()
{
    memset(h, -1, sizeof h);
    memset(dist, -1, sizeof dist);
    scanf("%d", &n);
    for (int i = 0; i < n - 1; i ++ )
    {
        int p, q, d;
        scanf("%d%d%d", &p, &q, &d);
        add(p, q, d);
        add(q, p, d);
    }
    int u = 1;
    bfs(u);
    for (int i = 1; i <= n; i ++ )
        if (dist[u] < dist[i])
            u = i;
    memset(dist, -1, sizeof dist);        
    bfs(u);
    for (int i = 1; i <= n; i ++ ) 
        if (dist[u] < dist[i])
            u = i;
    int s = dist[u];
    printf("%lld\n", 10 * s + (1ll + s) * s / 2);
    return 0;
}



目录
相关文章
|
11月前
|
移动开发 算法 机器人
[蓝桥杯] 二分与前缀和习题练习
又来更新了。二分与前缀和是蓝桥杯比较常考的内容,所以我们要多加练习这方面的习题。二分与前缀和的难度相对来说不算大,我们应该掌握其关键要点。
92 0
|
11月前
|
算法
[蓝桥杯] 递归与递推习题训练
蓝桥杯比赛只有四十天左右啦,最近会按照模块更新一些有关蓝桥杯算法题。学习算法不仅仅是为了参见比赛,更是以后找工作的一个敲门砖。废话不多说,我们直接看题。
65 0
|
存储 算法 Java
【数据结构】蓝桥杯常见习题(二)
【数据结构】蓝桥杯常见习题(二)
10964 0
|
存储 Java C#
【数据结构】蓝桥杯常见习题(一)
【数据结构】蓝桥杯常见习题(一)
639 0
|
存储 机器学习/深度学习 算法
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(下)
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(下)
227 0
|
C++
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(中)
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(中)
96 0
|
算法 C++
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(上)
蓝桥杯练习系统 基础练习 全部习题 题目及AC代码(包括VIP试题)C++(上)
150 0
|
算法 C++
蓝桥杯第十五讲--复杂dp【习题】
蓝桥杯第十五讲--复杂dp【习题】
233 0
蓝桥杯第十五讲--复杂dp【习题】
|
算法 C语言 C++
蓝桥杯第十四讲--数论【习题】
蓝桥杯第十四讲--数论【习题】
156 0
蓝桥杯第十四讲--数论【习题】
|
算法 C++
蓝桥杯第十三讲--树状数组与线段树【习题】
蓝桥杯第十三讲--树状数组与线段树【习题】
161 0
蓝桥杯第十三讲--树状数组与线段树【习题】