最小生成树的个数_最小生成树的实际应用

最小生成树的个数_最小生成树的实际应用给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个。输入格式第一行包含两个整数 N 和 M。接下来 M 行,每行包含三个整数 x,y,z,表示点 x 和点 y 之前存在一条边,边的权值为 z。输出格式包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)数据范围N≤105,M≤3×105输入样例:5 61 2 11 3 22 4 33 5 4


Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

给定一张 N 个点 M 条边的无向图,求无向图的严格次小生成树。

设最小生成树的边权之和为 sum,严格次小生成树就是指边权之和大于 sum 的生成树中最小的一个。

输入格式
第一行包含两个整数 N 和 M。

接下来 M 行,每行包含三个整数 x,y,z,表示点 x 和点 y 之前存在一条边,边的权值为 z。

输出格式
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

数据范围
N≤105,M≤3×105

输入样例:
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
输出样例:
11
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int M = 3 * 3e5 + 10;
const int maxbit = 20;
typedef long long ll;
int f[N][maxbit],d1[N][maxbit],d2[N][maxbit],height[N];
struct Edge{ 
   
    int u,v,w,next;
    bool f;
    bool operator<(const Edge a)const{ 
   
        return w < a.w;
    }
}edge[M];
int head[N],cnt;
int n,m;
int fa[N];
int Find(int x){ 
   
    return fa[x] = (fa[x] == x ? x : Find(fa[x]));
}
void add(int u,int v,int w){ 
   
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].next = head[u];
    head[u] = cnt ++;
}
void dfs(int u,int fa,int d,int w){ 
   
    f[u][0] = fa;
    height[u] = d;
    d1[u][0] = w,d2[u][0] = 0;
    for(int i = 1;i <= maxbit - 1;i ++){ 
   
        f[u][i] = f[f[u][i - 1]][i - 1];
        d1[u][i] = max(d1[u][i - 1],d1[f[u][i - 1]][i - 1]);
        if(d1[u][i - 1] == d1[f[u][i - 1]][i - 1])
            d2[u][i] = max(d2[u][i - 1],d2[f[u][i - 1]][i - 1]);
        if(d1[u][i - 1] > d1[f[u][i - 1]][i - 1])
            d2[u][i] = max(d1[f[u][i - 1]][i - 1],d2[u][i - 1]);
        else d2[u][i] = max(d1[u][i - 1],d2[f[u][i - 1]][i - 1]);
    }
    for(int i = head[u];~i;i = edge[i].next){ 
   
        int v = edge[i].v,ww = edge[i].w;
        if(v == fa)continue;
        dfs(v,u,d + 1,ww);
    }
}
int lca(int x,int y,int &a,int &b){ 
   
    a = b = 0;
    if(height[x] < height[y])swap(x,y);
    for(int i = maxbit - 1;i >= 0;i --){ 
   
        if(height[f[x][i]] >= height[y]){ 
   
            if(d1[x][i] > a)b = a,a = d1[x][i];
            else if(d1[x][i] != a && d1[x][i] > b)b = d1[x][i]; 
            if(d2[x][i] > a)b = a,a = d2[x][i];
            else if(d2[x][i] != a && d2[x][i] > b)b = d2[x][i];
            x = f[x][i];
        }
    }
    if(x == y)return x;
    for(int i = maxbit - 1;i >= 0;i --){ 
   
        if(f[x][i] != f[y][i]){ 
   
            int aa = d1[x][i],bb = d2[x][i],cc = d1[y][i],dd = d2[y][i];
            if(aa > a)b = a,a = aa;
            else if(aa != a && aa > b)b = aa;
            if(bb > a)b = a,a = bb;
            else if(bb != a && bb > b)b = bb; 
            if(cc > a)b = a,a = cc;
            else if(cc != a && cc > b)b = cc; 
            if(dd > a)b = a,a = dd;
            else if(dd != a && dd > b)b = dd; 
            x = f[x][i],y = f[y][i];
        }
    }
    int aa = d1[x][0],bb = d2[x][0],cc = d1[y][0],dd = d2[y][0];
    if(aa > a)b = a,a = aa;
    else if(aa != a && aa > b)b = aa;
    if(bb > a)b = a,a = bb;
    else if(bb != a && bb > b)b = bb; 
    if(cc > a)b = a,a = cc;
    else if(cc != a && cc > b)b = cc; 
    if(dd > a)b = a,a = dd;
    else if(dd != a && dd > b)b = dd; 
    return f[x][0];
}
int main(){ 
   
    memset(head,-1,sizeof head);
    cin>>n>>m;
    int x,y,w;
    for(int i = 0;i < m;i ++){ 
   
        cin>>x>>y>>w;
        edge[i].u = x,edge[i].v = y,edge[i].w = w;
        edge[i].f = false;
    }
    cnt = m;
    sort(edge,edge + m);
    for(int i = 0;i <= n;i ++)fa[i] = i;
    ll res = 0;
    for(int i = 0;i < m;i ++){ 
   
        int a = Find(edge[i].u),b = Find(edge[i].v),w = edge[i].w;
        if(a != b){ 
   
            fa[a] = b;
            edge[i].f = true;
            add(edge[i].u,edge[i].v,w),add(edge[i].v,edge[i].u,w);
            res += w;
        }
    }
    
    dfs(1,0,1,0);
    int xx,yy;
    ll t = 0x3f3f3f3f3f3f3f3f;
    for(int i = 0;i < m;i ++){ 
   
        if(!edge[i].f){ 
   
            int a = edge[i].u,b = edge[i].v,w = edge[i].w;
            int aa = 0,bb = 0;
            lca(a,b,aa,bb);
            if(aa == w){ 
   
                t = min(res + w - bb,t);
            }
            else t = min(res + w - aa,t);
        }
    }
    cout<<t<<endl;
    
    return 0;
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/169114.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • [Android Studio 权威教程]断点调试和高级调试

    [Android Studio 权威教程]断点调试和高级调试有人说Android的调试是最坑的,那我只能说是你不会用而已,我可以说AndroidStudio的调试是我见过最棒的。好了开始写一个简单的调试程序,我们先来一个for循环for(inti=0;i<10;i++){//获取当前i的值intselector=i;//打log查看当前i的值(此步多余,实际开发请忽略)Logger.e("fo

    2022年5月11日
  • HOOK消息钩子

    HOOK消息钩子大致的过程是当系统I/O上发生一个事件时,系统捕获该事件,并向指定的应用程序的消息队列发送一个消息,应用程序从消息队列中顺次取出一个消息,交由系统调度相应的窗口回调程序进行消息处理。这里可以看到,从OS捕捉到消息开始处理,到最后交还给OS调度回调函数,就像走了一个循环,我自己理解这也是为什么叫做“回调函数”的原因之一。接下来我们要进行的HOOK就是在上面的第二步和第三步之间进行的额外工作。钩子机制允许应用程序截获(且或)处理window消息或特定事件。钩子实际上是一个处理消息的程序段,通过系统调用,把

    2022年7月26日
  • 【不专一的开发】UML(二)—行为图(状态图、活动图、序列图、协同图)

    【不专一的开发】UML(二)—行为图(状态图、活动图、序列图、协同图)脑图,概念,例子,画图,翻来覆去,深入理解

    2022年5月18日
  • 数据挖掘算法与现实生活中的应用案例[通俗易懂]

    数据挖掘算法与现实生活中的应用案例[通俗易懂]如何分辨出垃圾邮件”、“如何判断一笔交易是否属于欺诈”、“如何判断红酒的品质和档次”、“扫描王是如何做到文字识别的”、“如何判断佚名的著作是否出自某位名家之手”、“如何判断一个细胞是否属于肿瘤细胞”等等,这些问题似乎都很专业,都不太好回答。但是,如果了解一点点数据挖掘的知识,你,或许会有柳暗花明的感觉。本文,主要想简单介绍下数据挖掘中的算法,以及它包含的类型。然后,通过现实中触手可及的、活生生的案例

    2022年6月19日
  • 安卓7.0以上安装fiddler证书(模拟器)

    安卓7.0以上安装fiddler证书(模拟器)1.fiddler,最好fiddler4以上fiddler官网下载即可DownloadFiddlerWebDebuggingToolforFreebyTelerikhttps://www.telerik.com/download/fiddler2.夜神模拟器(百度下载)3.安装jdk(jdk8能够更好的支持自动化工具)JavaDownloads|Oraclehttps://www.oracle.com/java/technologies/downloads/#j

    2022年7月7日
  • 下载和运行GitHub上的代码教程总结

    下载和运行GitHub上的代码教程总结从昨天开始就想着从GitHub上下载一个开源的Vue的实战项目,希望能从中学习更多的Vue的实用内容,结果搞了半天好不容易下载了,不知道怎么弄。然而,今天终于成功了,激动地我赶紧来记录一下。如何从GitHub上下载自己需要的项目:1.首先,你要有一个自己的GitHub(https://github.com/)的账号。关于如何注册GitHub的账号以及如何获取你的SSH密钥这个问题,请大家参…

    2022年6月4日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号