小C最近学了很多最小生成树的算法,Prim算法、Kurskal算法、消圈算法等等。正当小C洋洋得意之时,小P又来泼小C冷水了。小P说,让小C求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说:如果最小生成树选择的边集是EM,严格次小生成树选择的边集是ES,那么需要满足:(value(e)表示边e的权值) \sum_{e \in E_M}value(e)<\sum_{e \in E_S}value(e)∑e∈EM​​value(e)<∑e∈ES​​value(e)

这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

输入输出格式

输入格式:

 

第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

 


输出格式:

 

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

 

输入输出样例

输入样例#1:

5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
输出样例#1: 

11

题解:严格次小生成树和非严格次小生成树的思想其实差不多,无非是多维护一个u->v之间的次大值
然后这显然也是能用倍增维护的
如果把最大边拆去换成新边后整棵树仍是最小生成树,那么就换次大边用,再不对就不用
这样能保证求出的一定不是最小生成树,所以是严格次小的
代码如下:
#pragma GCC optimize(3)
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define mp make_pair
#define int long long
#define pii pair<long long,long long>
using namespace std; struct node
{
int from,to,cost;
} e[];
int n,m,f[],ans,ans1,vis[],fa[][],d1[][],d2[][],deep[];
vector<pii> g[]; int cmp(node a,node b)
{
return a.cost<b.cost;
} void dfs(int now,int ff,int dep,int dis)
{
deep[now]=dep;
d1[][now]=dis;
fa[][now]=ff;
for(int i=; i<=; i++)
{
fa[i][now]=fa[i-][fa[i-][now]];
}
for(int i=; i<=; i++)
{
register int a[];
a[]=d1[i-][now];
a[]=d1[i-][fa[i-][now]];
a[]=d2[i-][now];
a[]=d2[i-][fa[i-][now]];
sort(a,a+);
d1[i][now]=a[];
d2[i][now]=a[];
}
for(int i=; i<g[now].size(); i++)
{
if(g[now][i].first==ff) continue;
dfs(g[now][i].first,now,dep+,g[now][i].second);
}
} pii get1(int u,int v)
{
int di=0ll,di2=0ll;
if(deep[u]<deep[v]) swap(u,v);
for(int i=; i>=; i--)
{
if(deep[fa[i][u]]>=deep[v])
{
register int a[];
a[]=di;
a[]=di2;
a[]=d1[i][u];
a[]=d2[i][u];
sort(a,a+);
di=a[];
di2=a[];
u=fa[i][u];
}
}
if(u==v) return mp(di,di2);
for(int i=; i>=; i--)
{
if(fa[i][u]!=fa[i][v])
{
register int a[];
a[]=di;
a[]=di2;
a[]=d1[i][u];
a[]=d1[i][v];
a[]=d2[i][u];
a[]=d2[i][v];
sort(a,a+);
di=a[];
di2=a[];
u=fa[i][u];
v=fa[i][v];
}
}
register int a[];
a[]=di;
a[]=di2;
a[]=d1[][u];
a[]=d1[][v];
a[]=d2[][u];
a[]=d2[][v];
sort(a,a+);
di=a[];
di2=a[];
return mp(di,di2);
} void init()
{
for(int i=; i<=n; i++)
{
f[i]=i;
}
} int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
} void unity(int i,int x,int y,int cost)
{
int fx=find(x);
int fy=find(y);
if(fx==fy) return ;
ans+=cost;
f[fy]=fx;
g[x].push_back(mp(y,cost));
g[y].push_back(mp(x,cost));
vis[i]=;
} signed main()
{
scanf("%lld%lld",&n,&m);
init();
for(int i=; i<=m; i++)
{
scanf("%lld%lld%lld",&e[i].from,&e[i].to,&e[i].cost);
}
sort(e+,e+m+,cmp);
for(int i=; i<=m; i++)
{
unity(i,e[i].from,e[i].to,e[i].cost);
}
dfs(,,,);
ans1=1e16;
for(int i=; i<=m; i++)
{
if(!vis[i])
{
pii tmp=get1(e[i].from,e[i].to);
int ans2=ans-tmp.first+e[i].cost;
int ans3=ans-tmp.second+e[i].cost;
if(ans==ans2)
{
if(ans<ans3) ans1=min(ans1,ans3);
}
else
{
ans1=min(ans1,ans2);
}
}
}
printf("%lld\n",ans1);
}
 

BZOJ 1977 严格次小生成树的更多相关文章

  1. BZOJ 1977 严格次小生成树(算竞进阶习题)

    树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...

  2. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )

    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...

  3. [BeiJing2010组队][BZOJ 1977]次小生成树 Tree

    话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有:  (果然除我以外, ...

  4. BZOJ 1977 次小生成树(最近公共祖先)

    题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树. 先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值, ...

  5. BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树

    描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...

  6. 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree

    Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...

  7. bzoj 1977 洛谷P4180 严格次小生成树

    Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...

  8. 1977: [BeiJing2010组队]次小生成树 Tree

    1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...

  9. bzoj 1977

    题意:求严格的次小生成树.点n<=100000,m<=300000 思路:很容易想到先做一边最小生成树,然后枚举每条非树边(u, v, w),然后其实就是把u,v路径上小于w的最大边替换成 ...

随机推荐

  1. 各自平台token获取解析及用户信息的获取

    1.auth根据手机号码获取auth平台session_token记统一认证的user_id与pass_id [dwliuchao1@GD-QHD-CNG152TFKX-12.55 logs]$ cd ...

  2. KindEditor 和 xss过滤

    KindEditor   1.进入官网 2.下载 官网下载:http://kindeditor.net/down.php 本地下载:http://files.cnblogs.com/files/wup ...

  3. Qt(自适应窗口)

    关于窗口布局: 默认控件的大小为最小尺寸: 如果此时右键设置布局时,窗口大小会自动缩放对应大小,不利于调整. 建议窗口控件设置好最小尺寸,便于窗口布局时,控件不会变形,例如: 改变minimumsiz ...

  4. nexus3 搭建maven远程仓库

    右上角 下载maven http://maven.apache.org/download.cgi 下载nexus https://www.sonatype.com/download-oss-sonat ...

  5. 在Core环境下用WebRequest连接上远程的web Api 实现数据的简单CRUD(附Git地址)

    本文所有的东西都是在dot Net Core 1.1环境+VS2017保证测试通过. 本文接着上次文章接着写的,不了解上篇文章的可能看着有点吃力.我尽量让大家都能看懂.这是上篇文章的连接http:// ...

  6. springboot 的定时任务使用

    定时任务在Spring Boot中的集成 在启动类中加入开启定时任务的注解: 在SpringBoot中使用定时任务相当的简单.首先,我们在启动类中加入@EnableScheduling来开启定时任务. ...

  7. 学习ios一段过程后的思考

    现在回想起来,学习ios也有一段时间了,大概三个月不到吧,本来是搞linux驱动,刚开始来公司就我一个人负责驱动的东西,主要就是一些bug的解决,后来系统基本上稳定了,我就闲下来了,公司又有些移动医疗 ...

  8. quartz的配置文件

    quartz在运行时默认加载的是工程目录下的quartz.properties文件,如果工程目录下没有quartz.properties文件,它就会去读取quartz jar包下的quartz.pro ...

  9. 40行代码爬取猫眼电影TOP100榜所有信息

    主要内容: 一.基础爬虫框架的三大模块 二.完整代码解析及效果展示 1️⃣  基础爬虫框架的三大模块 1.HTML下载器:利用requests模块下载HTML网页. 2.HTML解析器:利用re正则表 ...

  10. kubernetes ServiceAccount

    api server 启动参数增加 –admission_control=…,ServiceAccount,…