【每日一题】Rinne Loves Edges

Rinne Loves Edges

https://ac.nowcoder.com/acm/problem/22598


题目

题目描述:
Rinne  最近了解了如何快速维护可支持插入边删除边的图,并且高效的回答一下奇妙的询问。
她现在拿到了一个 n 个节点 m 条边的无向连通图,每条边有一个边权 wi
现在她想玩一个游戏:选取一个 “重要点” S,然后选择性删除一些边,使得原图中所有除 S 之外度为 1 的点都不能到达 S。
定义删除一条边的代价为这条边的边权,现在 Rinne 想知道完成这个游戏的最小的代价,这样她就能轻松到达 rk1 了!作为回报,她会让你的排名上升一定的数量。

输入描述:
第一行三个整数 N,M,S,意义如「题目描述」所述。
接下来 M 行,每行三个整数 u,v,w 代表点 u 到点 v 之间有一条长度为 w 的无向边。

输出描述:
一个整数表示答案。


解析

这道题是一道简单的树形dp,只是我对树形dp(实则是对dp)不太熟,所以没想到求解方法。
  • 所以开头还是那句话:动态规划的基础就是递推

树形dp:
  1. 想要求解这道题,我们先要读懂题目的意思:我们要用最少的代价,使得当前根节点和所有叶子节点不相连(看题很重要,一开始我没发现是树)
  2. 然后到这里,我们就要想一下该怎么递推,该怎么把大问题分解成等同的小问题(我就是在这卡到了)
  3. 所有在这里,根据我们要做的事情:断开节点:我们应该想到以某一u(节点)为根节点的树对一条分支有两种断开方法
    <1>断开自己和某一v(子节点)之间的关系。<2>断开子节点v的所有子节点(一定是断开所有子节点,因为树的每一条分支最终一定以叶节点结束)
  4. 所以我们就能得到转移方程:(w表示u到某一分支的权值)。
  • 补充一句邓老师告诉我的话:树型dp本质上可以说是个搜索——遍历这棵树,在返回的时候维护相关的值。

打代码哦:
  1. 前向星保存树形关系。
  2. dfs进行优先遍历。(上面树形dp讲了详细方法)
  3. 其他重要的就是一点点操作顺序了吧,看代码~


AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long ll;
//代码预处理区

const int INF = 0x3f3f3f3f;
const int MAX = 1e5 + 7;
int head[MAX], tot;
struct Node {
    int v, w, next;
} edge[MAX << 1];
ll f[MAX];
//全局变量区

template<class T>inline void read(T& res);
void add_edge(int u, int v, int w);
void dfs(int u, int fa);
//函数预定义区

int main() {
    int N, M, S; read(N); read(M); read(S);
    tot = 0; memset(head,  0,  sizeof  head);
    for (int i = 1; i <= M; i++) {
        int u, v, w; read(u); read(v); read(w);
        add_edge(u, v, w);
        add_edge(v, u, w);
    }
        memset(f, 0, sizeof f);
    dfs(S, 0);
    printf("%lld", f[S]);
    return 0;
}
template<class T>inline void read(T& res) {
    char c; T flag = 1;
    while ((c = getchar()) < '0' || c > '9')
        if (c == '-')
            flag = -1;
    res = c - '0';
    while ((c = getchar()) >= '0' && c <= '9')
        res = res * 10 + c - '0';
    res *= flag;
}
void add_edge(int u, int v, int w) {
    tot++;
    edge[tot].v = v;
    edge[tot].w = w;
    edge[tot].next = head[u];
    head[u] = tot;
}
void dfs(int u, int fa) {
    int flag = 0;
    for (int i = head[u]; i; i = edge[i].next) {
        int v = edge[i].v;
        int w = edge[i].w;
        if (fa == v) continue;
        flag = 1;
        dfs(v, u);
        f[u] += min(f[v], (ll)w);
    }
    if (!flag) f[u] = INF;
}
//函数区

每日一题 文章被收录于专栏

憨憨的专栏

全部评论

相关推荐

最近又搬回宿舍了,在工位坐不住,写一写秋招起伏不断的心态变化,也算对自己心态的一些思考表演式学习从开始为实习准备的时候就特别焦虑,楼主一开始选择的是cpp后端,但是24届这个方向已经炸了,同时自己又因为本科非92且非科班,所以感到机会更加迷茫。在某天晚上用java写出hello&nbsp;world并失眠一整晚后选择老本行干嵌入式。理想是美好的,现实情况是每天忙但又没有实质性进展,总是在配环境,调工具,顺带还要推科研。而这时候才发现自己一直在表演式学习,徘徊在设想如何展开工作的循环里,导致没有实质性进展。现在看来当时如果把精力专注在动手写而不是两只手端着看教程,基本功或许不会那么差。实习的焦虑5月,楼主...
耶比:哲学上有一个问题,玛丽的房间:玛丽知道眼睛识别色彩的原理知道各种颜色,但是她生活在黑白的房间里,直到有一天玛丽的房门打开了她亲眼看到了颜色,才知道什么是色彩。我现在最大可能的减少对非工作事情的思考,如果有一件事困扰了我, 能解决的我就直接做(去哪里或者和谁吵架等等……),解决不了的我就不想了,每一天都是最年轻的一天,珍惜今天吧
投递比亚迪等公司10个岗位 > 秋招被确诊为…… 牛客创作赏金赛
点赞 评论 收藏
分享
牛客717484937号:双飞硕没实习挺要命的
点赞 评论 收藏
分享
10-07 20:48
门头沟学院 Java
听说改名就会有offer:可能是实习上着班想到后面还要回学校给导师做牛马,看着身边都是21-25的年纪,突然emo了了
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务