首页 > 其他分享 >严格次小生成树

严格次小生成树

时间:2024-06-04 19:55:16浏览次数:23  
标签:dp2 val int max 生成 严格 ans dp

如果我早点遇见你,结局是不是会不一样


模板题链接

很久没有写过这么长的代码了
重要部分就是对倍增 LCA 的改动

以下是代码,维护了最大边权和次大边权

// Created by qyy on 2024/6/4.

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

#define PII pair<int, int>
#define endl "\n"

const long long inf = 0x3f3f3f3f3f3f3f3f;
const int N = 3e5 + 10;
const int mod = 1e9 + 7;
#define int long long

int n, m, f[N];

int ekcnt = 0;
struct Edge_Kru{
    int from, to;
    ll val;
    bool flag;
}ek[N];

int head[N], cnt;
struct Edge{
    int from, to, nxt;
    ll val;
}e[N];
void add(int u, int v, ll val){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    e[cnt].val = val;
    head[u] = cnt;
}

bool cmp(Edge_Kru a, Edge_Kru b){
    return a.val < b.val;
}

int find_set(int x){
    if(f[x] != x) f[x] = find_set(f[x]);
    return f[x];
}
void merge_set(int x, int y){
    int fx = find_set(x), fy = find_set(y);
    if(fx != fy) f[fx] = fy;
}

ll dp[N][20], dp2[N][20]; // 分别是最大边权与次大边权

int fa[N][20], deep[N];
void dfs(int x, int father){
    deep[x] = deep[father] + 1;
    fa[x][0] = father;
    for(int i = 1; (1 << i) <= deep[x]; i++){
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
        dp[x][i] = max(dp[x][i - 1], dp[fa[x][i - 1]][i - 1]);
        dp2[x][i] = max(dp2[x][i - 1], dp2[fa[x][i - 1]][i - 1]);
        if(dp[x][i] > dp[x][i - 1]) dp2[x][i] = max(dp2[x][i], dp[x][i - 1]);
        if(dp[x][i] > dp[fa[x][i - 1]][i - 1]) dp2[x][i] = max(dp2[x][i], dp[fa[x][i]][i - 1]);
    }

    for(int i = head[x]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(v != father)
        {
            dp[v][0] = e[i].val;
            // 问题是 次大的该怎么维护呢。
            dp2[v][0] =  0;
            dfs(v, x);
        }
    }
}

// LCA 也得改,直接修改为查询函数
ll LCA(int x, int y, ll val){
    if(deep[x] < deep[y]) swap(x, y);
    // 目的找到第一个小于 val 的最大值
    ll ans = 0;
    for(int i = 19; i >= 0; i--)
        if(deep[x] - (1 << i) >= deep[y]){

            if(dp[x][i] == val){
                ans = max(ans, dp2[x][i]);
            }else{
                ans = max(ans, dp[x][i]);
            }
            x = fa[x][i];
        }

    if(x == y) return ans;
    // x 和 y 一起向上跳
    for(int i = 19; i >= 0; i--){
        if(fa[x][i] != fa[y][i]){
            if(dp[x][i] == val){
                ans = max(ans, dp2[x][i]);
            }else{
                ans = max(ans, dp[x][i]);
            }
            if(dp[y][i] == val){
                ans = max(ans, dp2[y][i]);
            }else{
                ans = max(ans, dp[y][i]);
            }

            x = fa[x][i];
            y = fa[y][i];
        }
    }
    if(dp[x][0] == val){
        ans = max(ans, dp2[x][0]);
    }else{
        ans = max(ans, dp[x][0]);
    }
    if(dp[y][0] == val){
        ans = max(ans, dp2[y][0]);
    }else{
        ans = max(ans, dp[y][0]);
    }
    return ans;
}

void solve() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++){
        f[i] = i;
    }
    for(int i = 1; i <= m; i++){
        int u, v;
        ll val;
        cin >> u >> v >> val;
        if(u != v)
            ek[++ekcnt] = {u, v, val, false};
    }
    ll ans = 0;
    int begid = 0;
    sort(ek + 1, ek + 1 + ekcnt, cmp);
    for(int i = 1; i <= ekcnt; i++){
        int u = ek[i].from, v = ek[i].to;
        ll val = ek[i].val;
        int fu = find_set(u), fv = find_set(v);
        if(fu != fv){
            ek[i].flag = true;
            merge_set(u, v);
            add(u, v, val);
            add(v, u, val);
            begid = i + 1;
            ans += val;
        }
    }
    // 建树建完了
    dfs(1, 0);

    ll ans2 = inf;
    for(int i = 1; i <= ekcnt; i++){
        if(ek[i].flag) continue;
        int u = ek[i].from, v = ek[i].to;
        if(u == v) continue;
        ll val = ek[i].val;
        ans2 = min(ans2, val - LCA(u, v, val));
    }
    cout << ans + ans2 << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t = 1;
    //cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}


我应该再也获得不了这样的机会了

标签:dp2,val,int,max,生成,严格,ans,dp
From: https://www.cnblogs.com/9102qyy/p/18231602

相关文章

  • 【VS Code使用】仅当从 VS 开发人员命令提示符处运行 VS Code 时,cl.exe 生成和调试才
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录一、前言......
  • Prompt提示词 | ChatGPT 1分钟快速生成学习计划
    我们在使用ChatGPT的时候,可能会遇到上下文记忆和限制的问题,这两天碰到类似的问题。大概场景是这样的,作为一个prompt的学习者,想要系统化的学习,需要ChatGPT帮我生成一份14天的学习打卡计划,学习方法采用经典的SQ3R学习法。SQ3R学习法,来自易学师姐丢丢可能是由于记忆和文本限......
  • 文心一言、通义千问、智谱清言、kimi,AI批量生成文章保存word软件2.0版说明
    AI批量生成文章2.0版已经打包上传,文末自行下载。AI批量软件工具集成了文心一言、通义千问、智谱清言、kimi一共18个接口。可同时选择5个不同接口,读取excel第2列多个内容生成文章,并保存word软件。每次最多5个不同接口多线程同时处理3行excel,直到excel所有行列内容处理完毕。同......
  • .Net项目快速生成数据库的实体类
    MySQL数据库在NuGet包管理中安装以下包,选择符合项目.Net版本的包Microsoft.EntityFrameworkCore.ToolsMicrosoft.EntityFrameworkCore.DesignMySql.EntityFrameworkCore 在程序包控制管理台执行以下命令Scaffold-DbContext"DataSource=localhost;InitialCatalog=mydb;......
  • 使用 JWT 生成token
    安装Nuget包:Microsoft.AspNetCore.Authentication.JwtBearerSystem.IdentityModel.Tokens.Jwt2. 然后,配置JWT服务和认证:在 Program.cs文件中usingMicrosoft.AspNetCore.Authentication.JwtBearer;usingMicrosoft.Extensions.DependencyInjection;usingMicrosoft.......
  • Lumière:开创性的视频生成模型及其应用
    视频内容创造领域迎来了突破性进展,但视频生成模型由于运动引入的复杂性而面临更多挑战。这些挑战主要源自运动的引入所带来的复杂性。时间连贯性是视频生成中的关键要素,模型必须确保视频中的运动在时间上是连贯和平滑的,避免出现不自然的跳跃或断裂。空间关系的准确性也至关重要......
  • .netCore System.Drawing.Common 发布,在CentOS 运行报错,生成图片流时。会因为不支持在
    报错:System.PlatformNotSupportedException:System.Drawing.Commonisnotsupportedonnon-Windowsplatforms.Seehttps://aka.ms/systemdrawingnonwindowsformoreinformation. >System.PlatformNotSupportedException:System.Drawing.Commonisnotsupported......
  • TS 小技巧: 使用元组生成联合类型
    前言在我们使用TypeScript开发业务的时候,也许你会遇到一个这样的问题:我们如何根据一个数组的值得到一个联合类型?这里向大家介绍一个开发小技巧:使用元组生成联合类型开发场景我们看下面一段ts代码:constcolors=['red','green','orange','blue'];//这里ts解析......
  • mybatis逆向生成文件攻略
    pom.xml<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache......
  • 博客园文章目录生成脚本v1.0:支持多级、过滤空行、可指定文章、自定义插入点
    使用说明:1.设置-申请JS权限,等待审核通过2.设置-页脚HTML代码,代码贴进去保存 样式说明:1.默认目录插到文章顶部,可以加入<divid="toc"></div>标签自定义插入位置。2.H1和H2是加粗体,其他的是正常体。自定义功能:catalogue(true):给所有文章生成目录catalogue(false):只......