BZOJ 1977 严格次小生成树
小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∈EMvalue(e)<∑e∈ESvalue(e)
这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。
输入输出格式
输入格式:
第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。
输出格式:
包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)
输入输出样例
5 6
1 2 1
1 3 2
2 4 3
3 5 4
3 4 3
4 5 6
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 严格次小生成树的更多相关文章
- BZOJ 1977 严格次小生成树(算竞进阶习题)
树上倍增+kruskal 要找严格次小生成树,肯定先要找到最小生成树. 我们先把最小生成树的边找出来建树,然后依次枚举非树边,容易想到一种方式: 对于每条非树边(u,v),他会与树上的两个点构成环,我 ...
- BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...
- [BeiJing2010组队][BZOJ 1977]次小生成树 Tree
话说这个[BeiJing2010组队]是个什喵玩意? 这是一道严格次小生成树,而次小生成树的做法是层出不穷的 MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有: (果然除我以外, ...
- BZOJ 1977 次小生成树(最近公共祖先)
题意:求一棵树的严格次小生成树,即权值严格大于最小生成树且权值最小的生成树. 先求最小生成树,对于每个不在树中的边,取两点间路径的信息,如果这条边的权值等于路径中的权值最大值,那就删掉路径中的次大值, ...
- BZOJ 1977[BeiJing2010组队]次小生成树 Tree - 生成树
描述: 就是求一个次小生成树的边权和 传送门 题解 我们先构造一个最小生成树, 把树上的边记录下来. 然后再枚举每条非树边(u, v, val),在树上找出u 到v 路径上的最小边$g_0$ 和 严格 ...
- 【刷题】BZOJ 1977 [BeiJing2010组队]次小生成树 Tree
Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一 ...
- bzoj 1977 洛谷P4180 严格次小生成树
Description: 给定一张N个节点M条边的无向图,求该图的严格次小生成树.设最小生成树边权之和为sum,那么严格次小生成树就是边权之和大于sum的最小的一个 Input: 第一行包含两个整数N ...
- 1977: [BeiJing2010组队]次小生成树 Tree
1977: [BeiJing2010组队]次小生成树 Tree https://lydsy.com/JudgeOnline/problem.php?id=1977 题意: 求严格次小生成树,即边权和不 ...
- bzoj 1977
题意:求严格的次小生成树.点n<=100000,m<=300000 思路:很容易想到先做一边最小生成树,然后枚举每条非树边(u, v, w),然后其实就是把u,v路径上小于w的最大边替换成 ...
随机推荐
- xargs的i参数
xargs与find经常结合来进行文件操作,平时删日志的时候只是习惯的去删除,比如 # find . -type f -name "*.log" | xargs rm -rf * ...
- K老在拿图灵奖时的发言:Computer Programming as an Art
很多话说得很透彻,把一些觉比较精彩的摘抄一下. ... It seems to me that if the authors I studied were writing today, they wo ...
- autofs文件自动挂载系统
为了自己使用方便,利用iso文件制作了自己的rhel6.4的yum源,每次都手动进行mount,十分不便 后来在/etc/rc.local中写入了mount命令,方便多了. 时间一久,发现新的问题出现 ...
- U3D中的又一个坑
using System.Collections; using System.Collections.Generic; using UnityEditor; using UnityEngine; pu ...
- PHP 性能优化之 PHP-FPM
简介: PHP-FPM 是一个 PHP FastCGI 管理器,一般 Nginx 上面跑 PHP 程序都会将 PHP 程序丢给 PHP-FPM 来解析.好了,就这样! PHP 5.4 开始集成了 PH ...
- select sum也会返回null值
SELECT SUM(detail.VAL) FROM AI_SDP_ORDER_MONTH_DETAIL_201706 detail 如果所有的VAL都是null的话,或者根本就不存在 ...
- 结对作业——四则运算 Part3. 对于结对编程的总结与思考
结对作业——四则运算 Part3. 对于结对编程的总结与思考 PB15061303 刘梓轩PB16061489 艾寅中 GITHUB 地址 戳这里 目录 Part 1. Core代码编写部分 Part ...
- Nginx实现ssl一级、二级域名证书部署并用https访问代理转发服务器
1. 规划 域名 解析IP Nginx代理 htpps://www.devcult.com 47.88.10.155 htpps://auto.devcult.com 47.88.10.155 ...
- 刷题向》一道简单的思路题BZOJ1800(EASY+)
这道题其实并不难,主要原因是数据范围很小,当然数据如果大来也可以优化,但重点是在做的时候用的思路很通用, 所以本题是一道思想题(当然思想也不难) 标题里的“+”体现在一些边界处理中. 直接甩题目 De ...
- 《Android Studio实用指南》7.1 AndroidStudio代码检查工具概述
本文节选自<Android Studio实用指南> 作者: 毕小朋 目前本书已上传到百度阅读, 在百度中搜索[Anroid Studio实用指南]便可以找到本书. Android Stud ...