首页 > 其他分享 >洛谷OI_树的刷题笔记

洛谷OI_树的刷题笔记

时间:2025-01-22 23:53:36浏览次数:1  
标签:洛谷 OI int Alledge vis return include id 刷题

整个笔记注意力惊人,慎入......

持续更新。

P2700 逐个击破

能卡住我的黄题已经很少见了,但这道题确实又是一个。唉,只能说自己依然是蒟蒻吧。

不过,由于题目很容易理解,加上自己因为刷难题身心俱疲,“玩”一下这种简单的题目也算是种放松。

不能因为刷题,把自己学算法的乐趣搞没了。

先上个TLE代码,也就排序那一步和kruskal有点关系。

从权重最小的边开始,判断它所连两结点是否与标记结点相连,如果是,则删去。

但它确实是我自己发明的做法。

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#define int unsigned long long
using namespace std;

int n, m, k;
int mark[100005] = { 0 };
int cut[100005] = { 0 };
int vis[100005] = { 0 };

struct Edge
{
int u, v, w, id;
};

vector<Edge> e[100005];
vector<Edge> Alledge;

bool cmp(Edge& a, Edge& b) {

    return a.w < b.w;
}

bool islink(int top) {
    if (mark[top]) return true;
    for (auto [u, v, w, id] : e[top]) {
        if (vis[id]) continue;
        vis[id] = 1;
        bool res = islink(v);
        vis[id] = 0;
        if (res) return true;
    }
    return false;
}

signed main()
{
    cin >> n >> k;
    int u, v, w;
    int ans = 0;
    int x;
    for (int i = 1; i <= k; i++) {
        cin >> x;
        mark[x] = 1;
    }
    for (int i = 1; i <= n - 1; i++) {
        cin >> u >> v >> w;
        e[u].push_back({ u,v,w,i });
        e[v].push_back({ v,u,w,i });
        Alledge.push_back({ u,v,w,i });
    }
    sort(Alledge.begin(), Alledge.end(), cmp);

    for (auto [u, v, w, id] : Alledge) {
        vis[id] = 1;
        if (islink(u) and islink(v)) ans += w, k--;
        else vis[id] = 0;
        if (!k) break;
    }

    cout << ans;
    return 0;
}

好的,接下来我们开始卡常。

可以知道开销主要就是在判断是否与标记结点连通这一步。

注意到连接两个标记结点的边必须断开,所以可以先预处理一下:

for (int i = 1; i <= n - 1; i++) {
    cin >> u >> v >> w;
    if (mark[u] and mark[v]) {
        ans += w;
        continue;
    }
    e[u].push_back({ u,v,w,i });
    e[v].push_back({ v,u,w,i });
    Alledge.push_back({ u,v,w,i });
}

还是超时。

注意到

for (auto [u, v, w, id] : Alledge) {
    vis[id] = 1;
    if (islink(u) and islink(v)) ans += w, k--;
    else vis[id] = 0;
    if (!k) break;
}

else vis[id] = 0是不需要的。读者应该不难理解......形象一点说,如果这个边不连接特殊结点,那么后续也就不必通过此边来寻找特殊结点。

还是超时......

注意到有些边是不用进行判断的:如果它与前一个判断的边直接相连,如果前一条边断开了,那么它就一定不连接标记结点的边。

bool islink(int top) {
    if (mark[top]) return true;
    for (auto [u, v, w, id] : e[top]) {
        if (vis[id]) continue;
        vis[id] = 1;
        bool res = islink(v);
        if (res) {
            vis[id] = 0;
            return true;
        }
    }
    return false;
}

居然过了......

那么,这和kruskal算法的关系是什么......

注意到可以先把所有边除掉,然后去连可以连的边,把被标记点视作一个连通域。kruskal算法是不会在连通域间相连的。

连边时,需要先连代价最大的......

#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <cstring>
#define int unsigned long long
using namespace std;

int n, m, k;
int rt[100005] = { 0 };

struct Edge
{
    int u, v, w, id;
};

vector<Edge> Alledge;

bool cmp(Edge& a, Edge& b) {

    return a.w > b.w;
}

int findroot(int x) {
    return x == rt[x] ? x : rt[x] = findroot(rt[x]);
}

void un(int x, int y) {
    rt[findroot(x)] = findroot(y);
}

signed main()
{
    cin >> n >> k;
    int u, v, w;
    int ans = 0;
    int x;
    int pre = 0;
    for (int i = 1; i <= n; i++) rt[i] = i;
    for (int i = 1; i <= k; i++) {
        cin >> x;
        if (pre) {
            rt[x] = pre;
        }
        else pre = x;
    }
    for (int i = 1; i <= n - 1; i++) {
        cin >> u >> v >> w;
        ans += w;
        Alledge.push_back({ u,v,w,i });
    }
    sort(Alledge.begin(), Alledge.end(), cmp);
    for (auto [u, v, w, id] : Alledge) {
        int xr = findroot(u), yr = findroot(v);
        if (xr != yr) {
            un(xr, yr);
            ans -= w;
        }
    }
    cout << ans;
    return 0;
}

标签:洛谷,OI,int,Alledge,vis,return,include,id,刷题
From: https://www.cnblogs.com/tomorin/p/18686978

相关文章

  • 如何绕过 NaughtCoin 合约的时间锁(TimeLock)限制:基于 ERC20 的攻击合约分析
    简介在这个博客中,我们将探讨如何绕过一个ERC20合约中的时间锁机制(TimeLock),以便在锁定期内转移代币。我们以NaughtCoin合约为例,展示了如何编写攻击合约,并详细分析了如何解决出现的授权错误问题。我们会分步骤地解释这一过程,确保您能够理解如何利用ERC20标准进行安全性分......
  • NOIP 2024 游记
    省流:比CSP高。可见我CSP打的有多差。Day-?NOIP模拟赛就没有上过250。每场都是爆爆爆。Day-1带上了南极星给的挂坠。然后在火车上被刮破了。啊啊啊我对不起你。这次在火车上没有开摆,因为后有L前有BW根本没有好的卡视角的位置。中午晚上吃的都是燕大食堂,听说高......
  • 题解:洛谷 P1803 凌乱的yyy / 线段覆盖
    题目https://www.luogu.com.cn/problem/P1803题目大意给定  条线段,第  条线段放在位置 ,现在你需要从这些线段中拿出一些,使得剩下的线段不会重叠。思路考虑贪心。可以发现,按照左端点从小到大排序毫无意义(虽然样例能过)。因此考虑按右端点从小到大排序。然后尽量多放......
  • [SDOI2016小学组] 数苹果(apple)
    题目描述苹果丰收了,有n堆苹果,小红就在苹果堆旁。小红已经知道了每堆苹果有多少个。她要问一问从第a堆到第b堆一共有多少个苹果。输入输入数字n,然后输入n个数据。再输入问m,然后输入c行数据。输出输出m次a到b堆一共有多少个。样例输入 复制51234......
  • Android图形层垂直同步虚拟VSYNC机制
    简介某次调图形性能的时候(启动后台录屏,下(或)称case)发现AndroidSurfaceFlingerVsync机制并没有以前想的这么简单粗糙,特别是这次调图形性能发现一些跟Vsync有关联,因此做个总结详解。跟不上旋律节奏的VSYNC一份追踪报告,发现Vsync信号非常不规律,于是从这里入手分析、总结Vsync。......
  • 洛谷题单指南-线段树的进阶用法-P4602 [CTSC2018] 混合果汁
    原题链接:https://www.luogu.com.cn/problem/P4602题意解读:在一堆果汁中选出若干果汁,使得最小的美味度最大,且总体价格小于等于g,总体体积大于L,求这个最大的美味度。解题思路:显然,应该对答案进行二分,二分到一个美味度x,那么接下来check()函数要做的事,就是在所有美味度>=x的果汁中,查......
  • 【Stable Diffusion】SD安装、常用模型(checkpoint、embedding、LORA)、提示词具、常用
    StableDiffusion,一款强大的AI模型,让我们能够创造出惊人的艺术作品。本文将为您介绍如何安装StableDiffusion以及深入使用的学习教程。1.安装StableDiffusion(主义需要的小伙伴可以文末自行扫描获取)StableDiffusion的安装可能是第一步,但它绝对是重要的一步。以下是......
  • 打卡信奥刷题(647)用C++信奥P8342[普及组/提高] [COCI2021-2022#6] Med
    [COCI2021-2022#6]Med题目描述今天是公开赛的最后一轮。人们知道这两个比赛采用相同的计分系统。更准确地说,两场比赛都有666轮,每轮的积分在......
  • 打卡信奥刷题(645)用C++信奥P8318[普及组/提高] 『JROI-4』淘气的猴子
    『JROI-4』淘气的猴子题目背景众所周知,jockbutt是一个可爱的女孩纸。题目描述jockbutt有一个正整数序列,长度为nnn,分别为......
  • Android 12.0 系统添加自定义屏保并设置为默认屏保功能实现
    1.前言在12.0的系统rom定制化开发中,在进行相关项目开发的过程中,由于需要在系统锁屏休眠的时候,需要显示相关的背景,就是自定屏保功能,所以就需要添加自定义的屏保,然后在上一篇已经实现在进行锁屏休眠的时候进入屏保的功能,这里就介绍下自定义屏保和设置默认屏保功能就可以了2.......