传送门

分析

次小生成树的求法有两种,最大众的一种是通过倍增LCA找环中最大边求解,而这里我介绍一种神奇的O(nlogn) 做法:

我们先建立最小生成树,因为我们用kruskal求解是边的大小已经按升序排列,所以相同情况下,先枚举的边一定更优,所以我们每一次暴力的找非树边所连两点的LCA,并在寻找过程中对经过的边染色同时将其加入并查集以防止其二次查询(为何只需查找一次之前已经说过),然后在最后,我们只需找出所染颜色所代表的边的权值减去被染色的边的权值的最小值即可。因为被染色的树边共有n-1条,所以此过程的复杂度是O(m),因此总复杂度即为快排复杂度O(mlogm)。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<ctime>
#include<cctype>
using namespace std;
long long fa[110000],tot,used[310000],f[110000],col[310000],dep[110000];
long long ari[110000],is[110000];
long long sum=1;
struct node{
    long long x,y,z;
}d[310000];
struct edge{
    long long from,to,nxt,w,id;
}e[610000];
long long head[610000];
void add(long long x,long long y,long long z,long long id){
    e[sum].to=y;
    e[sum].nxt=head[x];
    e[sum].w=z;
    e[sum].id=id;
    head[x]=sum++;
    e[sum].to=x;
    e[sum].nxt=head[y];
    e[sum].w=z;
    e[sum].id=id;
    head[y]=sum++;
    return;
}
bool cmp(const node &p,const node &q){
    return p.z<q.z;
}
long long sf(long long a){
    return fa[a]==a?a:fa[a]=sf(fa[a]);
}
void dfs(long long a,long long fat){
    long long i,j,k;
    for(i=head[a];i;i=e[i].nxt)
       if(e[i].to!=fat){
        dep[e[i].to]=dep[a]+1;
        f[e[i].to]=a;
        ari[e[i].to]=e[i].id;
        dfs(e[i].to,a);
    }
    return;
}
long long ff(long long a){
    return is[a]==a?a:is[a]=ff(is[a]);
}
void mer(long long u,long long v,long long c){
    u=ff(u),v=ff(v);
    while(u!=v){
        if(dep[u]<dep[v])swap(u,v);
        col[ari[u]]=c;
        is[u]=ff(f[u]);
        u=ff(u);
    }
    return;
}
int main(){
    //freopen("1.in","r",stdin);
    long long n,m,i,j,k;
    scanf("%lld%lld",&n,&m);
    for(i=1;i<=m;i++){
       scanf("%lld%lld%lld",&d[i].x,&d[i].y,&d[i].z);
    }
    //建最小生成树
    sort(d+1,d+m+1,cmp);
    long long cnt=0,p,q;
    for(i=1;i<=n;i++){
       fa[i]=i;
       f[i]=i;
       is[i]=i;
    }
    for(i=1;i<=m;i++){
        p=sf(d[i].x),q=sf(d[i].y);
        if(p!=q){
            cnt++;
            if(rand()%2)fa[p]=q;
              else fa[q]=p;        
            tot+=d[i].z;
            used[i]=1;
            add(d[i].x,d[i].y,d[i].z,i);
        }
        if(cnt==n-1)break;
    }
    //初始化,f表示父子关系,is用于新并查集
    dfs(1,0);
    for(i=1;i<=m;i++)
       if(!used[i]){
            mer(d[i].x,d[i].y,i);
       }
    //求答案
    long long ans=1000000007;
    for(i=1;i<=m;i++)
       if(used[i]){
            if(col[i]&&d[col[i]].z!=d[i].z)
              ans=min(ans,d[col[i]].z-d[i].z);
       }
    printf("%lld\n",ans+tot);
    return 0;
}

p4180 次小生成树的更多相关文章

  1. P4180 【模板】严格次小生成树[BJWC2010]

    P4180 [模板]严格次小生成树[BJWC2010] 倍增(LCA)+最小生成树 施工队挖断学校光缆导致断网1天(大雾) 考虑直接枚举不在最小生成树上的边.但是边权可能与最小生成树上的边相等,这样删 ...

  2. 【luogu P4180 严格次小生成树[BJWC2010]】 模板

    题目链接:https://www.luogu.org/problemnew/show/P4180 这个题卡树剖.记得开O2. 这个题inf要到1e18. 定理:次小生成树和最小生成树差距只有在一条边上 ...

  3. 【题解】洛谷P4180 [BJWC2010] 严格次小生成树(最小生成树+倍增求LCA)

    洛谷P4180:https://www.luogu.org/problemnew/show/P4180 前言 这可以说是本蒟蒻打过最长的代码了 思路 先求出此图中的最小生成树 权值为tot 我们称这棵 ...

  4. Luogu P4180 【模板】严格次小生成树[BJWC2010]

    P4180 [模板]严格次小生成树[BJWC2010] 题意 题目描述 小\(C\)最近学了很多最小生成树的算法,\(Prim\)算法.\(Kurskal\)算法.消圈算法等等.正当小\(C\)洋洋得 ...

  5. 洛谷P4180【Beijing2010组队】次小生成树Tree

    题目描述: 小C最近学了很多最小生成树的算法,Prim算法.Kurskal算法.消圈算法等等.正当小C洋洋得意之时,小P又来泼小C冷水了.小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还 ...

  6. P4180 [BJWC2010]严格次小生成树

    P4180 [BJWC2010]严格次小生成树 P4180 题意 求出一个无向联通图的严格次小生成树.严格次小生成树的定义为边权和大于最小生成树的边权和但不存在另一棵生成树的边权和在最小生成树和严格次 ...

  7. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

  8. P4180 严格次小生成树[BJWC2010] Kruskal,倍增

    题目链接\(Click\) \(Here\). 题意就是要求一个图的严格次小生成树.以前被题面吓到了没敢做,写了一下发现并不难. 既然要考虑次小我们就先考虑最小.可以感性理解到一定有一种次小生成树,可 ...

  9. [Luogu P4180][BJWC 2010]严格次小生成树

    严格次小生成树,关键是“严格”,如果是不严格的其实只需要枚举每条不在最小生成树的边,如果得到边权和大于等于最小生成树的结束就行.原理就是因为Kruskal非常贪心,只要随便改一条边就能得到一个非严格的 ...

随机推荐

  1. 【六】MongoDB管理之副本集

    一.复制介绍 所谓的复制就是在多个主机之间同步数据的过程. 1.数据冗余及可用性 复制技术提供数据冗余及可用性,在不同的数据库服务器上使用多个数据副本,复制技术防止单个数据库服务器出现数据故障而出现数 ...

  2. 2014暑假ACM13级一批集训内容

    2014 这个暑假,我大一的暑假来吧!!! 2014暑假ACM13级一批集训内容 集训期间时间安排: 周一到周六 上午:8:00-11:30 下午:2:00-5:30 晚上7:00-9:30 周日自由 ...

  3. HTTPSQS(HTTP Simple Queue Service)消息队列

    HTTPSQS(HTTP Simple Queue Service)是一款基于 HTTP GET/POST 协议的轻量级开源简单消息队列服务,使用 Tokyo Cabinet 的 B+Tree Key ...

  4. 关于mysql使用索引的一个问题

    mysql一直号称是免维护的,但是我发现它往往连最表基本索引都不能自动维护,情景如下: 1.我用mysqldump导出一个大表longformh; 2.用mysql.exe导入到一个新库中: 3.查看 ...

  5. 算法(Algorithms)第4版 练习 2.1.1

    E A S Y Q U E S T I O N A E S Y Q U E S T I O N A E S Y Q U E S T I O N A E E Y Q U S S T I O N A E ...

  6. php把字符串指定字符分割成数组

    <?php $str="1|2|3|4|5|"; $var=explode("|",$str); print_r($var); ?> $var=ex ...

  7. asp.net中关于《%=》《%#》《%》 的用法——(转帖)

    1:在.aspx页面,<% %>标签相当于在.cs页面的代码,也就是说你在.cs文件里面怎样写,就可以在.aspx文件里面的<% %>标签里面怎样写. 2:在.aspx页面,& ...

  8. OpenCv-Python 图像滤波

    均值滤波 均值滤波函数cv2.blur() import cv2 img = cv2.imread('01.jpg') blur = cv2.blur(img,(5,5)) cv2.imshow( ...

  9. CodeForces - 1C:Ancient Berland Circus (几何)

    Nowadays all circuses in Berland have a round arena with diameter 13 meters, but in the past things ...

  10. [BZOJ1396&2865]识别子串

    bzoj1396 bzoj2865 dbzoj1396 dbzoj2865 题面 XX在进行字符串研究的时候,遇到了一个十分棘手的问题. 在这个问题中,给定一个字符串\(S\),与一个整数\(K\), ...