OJ题号:
  BZOJ1977、COGS2453

题目大意:
  给你一个无向连通图,求严格次小生成树。

思路:
  对于一般次小生成树,我们有一个结论:一般次小生成树一定可以通过替换掉最小生成树某一条边得到。
  因此对于一般次小生成树,我们只需要枚举不在MST上的每一条边,并枚举这条边对应两点路径上的所有边,尝试交换这两条边即可。
  显然枚举树上每一条边的复杂度是O(n)的,会TLE,因此我们可以用树剖或者树上倍增的方法记录区间最大边。
  然而这题要求的是严格次小生成树,所以万一你枚举的这两条边相等就WA了。
  为了保险起见,我们再记录区间最大边的同时,还要记录区间严格次大边。
  然后枚举的时候只要判断当前区间最大边是否和那条非树边相等,如果相等的话就取那条次大边即可。
  一开始因为没有权限号就去COGS上交,然后随随便便就A了,还跑了Rank1。
  但是据说那里数据比较水,就找q234rty借了权限号,去BZOJ上交,果然WA了。
  随机了一个小数据,发现是最后倍增求最大树边的时候最后一层没跳上去。
  去网上拉了一个程序对拍,发现无限WA。
  拿了一个数据手动模拟了一遍,发现原来是网上的题解错了。。

 #include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const long long inf=0x7fffffffffffffffll;
const int V=,logV=;
inline int log2(const float x) {
return ((unsigned&)x>>&)-;
}
class DisjointSet {
private:
int anc[V];
int Find(const int &x) {
return x==anc[x]?x:anc[x]=Find(anc[x]);
}
public:
DisjointSet() {
for(register int i=;i<V;i++) {
anc[i]=i;
}
}
void Union(const int &x,const int &y) {
anc[Find(x)]=Find(y);
}
bool isConnected(const int &x,const int &y) {
return Find(x)==Find(y);
}
};
DisjointSet s;
struct Edge1 {
int u,v,w;
bool inMST;
bool operator < (const Edge1 &another) const {
return w<another.w;
}
};
std::vector<Edge1> e1;
struct Edge {
int to,w;
};
std::vector<Edge> e[V];
inline void add_edge(const int &u,const int &v,const int &w) {
e[u].push_back((Edge){v,w});
}
long long mst=;
inline void kruskal() {
std::sort(e1.begin(),e1.end());
for(register unsigned i=;i<e1.size();i++) {
const int &u=e1[i].u,&v=e1[i].v,&w=e1[i].w;
if(s.isConnected(u,v)) continue;
s.Union(u,v);
add_edge(u,v,w);
add_edge(v,u,w);
e1[i].inMST=true;
mst+=w;
}
}
int anc[V][logV],max[V][logV],max2[V][logV];
int dep[V];
std::queue<int> q;
inline void bfs() {
q.push();
while(!q.empty()) {
const int x=q.front();
q.pop();
dep[x]=dep[anc[x][]]+;
for(register int i=;i<=log2(dep[x]);i++) {
anc[x][i]=anc[anc[x][i-]][i-];
max[x][i]=std::max(max[x][i-],max[anc[x][i-]][i-]);
if(max[x][i-]!=max[anc[x][i-]][i-]) {
max2[x][i]=std::min(max[x][i-],max[anc[x][i-]][i-]);
} else {
max2[x][i]=std::max(max2[x][i-],max2[anc[x][i-]][i-]);
}
}
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i].to;
if(y==anc[x][]) continue;
anc[y][]=x;
max[y][]=e[x][i].w;
q.push(y);
}
}
}
inline int maxEdge(int x,int y,const int &w) {
int tmax=;
while(dep[x]!=dep[y]) {
if(dep[x]<dep[y]) std::swap(x,y);
for(register int i=log2(dep[x]);i>=;i--) {
if(dep[anc[x][i]]>=dep[y]) {
if(max[x][i]<w) {
tmax=std::max(tmax,max[x][i]);
} else if(max2[x][i]<w) {
tmax=std::max(tmax,max2[x][i]);
}
x=anc[x][i];
}
}
}
if(x==y) return tmax;
for(register int i=log2(dep[x]);i>=;i--) {
if(anc[x][i]!=anc[y][i]) {
if(max[x][i]<w) {
tmax=std::max(tmax,max[x][i]);
} else if(max2[x][i]<w) {
tmax=std::max(tmax,max2[x][i]);
}
if(max[y][i]<w) {
tmax=std::max(tmax,max[y][i]);
} else if(max2[y][i]<w) {
tmax=std::max(tmax,max2[y][i]);
}
x=anc[x][i],y=anc[y][i];
}
}
if(max[x][]<w) {
tmax=std::max(tmax,max[x][]);
} else if(max2[x][]<w) {
tmax=std::max(tmax,max2[x][]);
}
if(max[y][]<w) {
tmax=std::max(tmax,max[y][]);
} else if(max2[y][]<w) {
tmax=std::max(tmax,max2[y][]);
}
return tmax;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("secmst.in","r+",stdin);
freopen("secmst.out","w+",stdout);
#endif
int n=getint(),m=getint();
for(register int i=;i<=m;i++) {
const int u=getint(),v=getint(),w=getint();
e1.push_back((Edge1){u,v,w,false});
}
kruskal();
bfs();
long long ans=inf;
for(register unsigned i=;i<e1.size();i++) {
if(e1[i].inMST) continue;
const int &u=e1[i].u,&v=e1[i].v,&w=e1[i].w;
ans=std::min(ans,mst-maxEdge(u,v,w)+w);
}
printf("%lld\n",ans);
#ifndef ONLINE_JUDGE
fclose(stdin),fclose(stdout);
#endif
return ;
}

[BJOI2010]次小生成树的更多相关文章

  1. [BJOI2010] 严格次小生成树

    题目链接 一个严格次小生成树的模板题. 看到次小生成树,我们有一个很直观的想法就是先构造出来最小生成树,然后将这个最小生成树上面最大的一条边替换成和它值最相近而且比他大的边. 那么首先就是用krusk ...

  2. HDU 4081Qin Shi Huang's National Road System(次小生成树)

    题目大意: 有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点.秦始皇希望这所有n-1条路长度之和最短.然后徐福突然有冒出来,说是他有魔法,可以不用人力.财力就变 ...

  3. POJ1679 The Unique MST[次小生成树]

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28673   Accepted: 10239 ...

  4. The Unique MST(次小生成树)

    Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 22335   Accepted: 7922 Description Give ...

  5. URAL 1416 Confidential --最小生成树与次小生成树

    题意:求一幅无向图的最小生成树与最小生成树,不存在输出-1 解法:用Kruskal求最小生成树,标记用过的边.求次小生成树时,依次枚举用过的边,将其去除后再求最小生成树,得出所有情况下的最小的生成树就 ...

  6. POJ1679The Unique MST(次小生成树)

    The Unique MST Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 25203   Accepted: 8995 D ...

  7. [kuangbin带你飞]专题八 生成树 - 次小生成树部分

    百度了好多自学到了次小生成树 理解后其实也很简单 求最小生成树的办法目前遇到了两种 1 prim 记录下两点之间连线中的最长段 F[i][k] 之后枚举两点 若两点之间存在没有在最小生成树中的边 那么 ...

  8. URAL 1416 Confidential(次小生成树)

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1416 Zaphod Beeblebrox — President of the Impe ...

  9. ACM题目————次小生成树

    Description 最小生成树大家都已经很了解,次小生成树就是图中构成的树的权值和第二小的树,此值也可能等于最小生成树的权值和,你的任务就是设计一个算法计算图的最小生成树. Input 存在多组数 ...

随机推荐

  1. 使用qt写的进制转换器

    没有使用什么数据结构,直接使用qt自带的进制转换函数, 实时出结果,代码在后面的链接中,由于初学qt,好多不会,代码构造就有点乱 截图如下

  2. BigDecimal常用方法

    一.介绍 Java中提供了大数字(超过16位有效位)的操作类,即 java.math.BinInteger 类和 java.math.BigDecimal 类,用于高精度计算. 其中 BigInteg ...

  3. ASP .Net Core系统部署到SUSE 16 Linux Enterprise Server 12 SP2 64 具体方案

    .Net Core 部署到 SUSE 16 Linux Enterprise Server 12 SP2 64 位中的步骤 1.安装工具 1.apache 2..Net Core(dotnet-sdk ...

  4. docker使用Dockerfile构建ssh容器

    一.使用Dockerfile构建centos 1.创建 Dockerfile mkdir centos # 创建一个目录存放之后的Dockerfile,目录名无所谓 cd centos # 进入目录 ...

  5. R vs Python:载入包 import & library

    数据科学:R & Python 工作 & Kaggle机器学习比赛 可重复函数式编程 一.Python模块的载入 包 Package 模块 module import pandas a ...

  6. Robots.txt 不让搜索引擎收录网站的方法

    有没有担心过自己的隐私会在强大的搜索引擎面前无所遁形?想象一下,如果要向世界上所有的人公开你的私人日记,你能接受吗?的确是很矛盾的问题,站长们大都忧虑“如何让搜索引擎收录的我的网站?”,而我们还是要研 ...

  7. hdu 5112 (2014北京现场赛 A题)

    给出某个时刻对应的速度 求出相邻时刻的平均速度 输出最大值 Sample Input23 // n2 2 //t v1 13 430 31 52 0 Sample OutputCase #1: 2.0 ...

  8. Java学习(Map接口)

    一.概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式不同,如下图. 1. Collection中的集合,元素是孤立存在的(理解为单身), ...

  9. s12-day01-work01用户登录接口

    README # README.md # day001-work-1 @南非波波 功能实现:登录接口 流程图: ![](http://i.imgur.com/61eFd0u.jpg) 程序实现: 1. ...

  10. thinkphp5.0与thinkphp3.2之间的区别

    5.0版本和之前版本的差异较大,本篇对熟悉3.2版本的用户给出了一些5.0的主要区别. URL和路由 5.0的URL访问不再支持普通URL模式,路由也不支持正则路由定义,而是全部改为规则路由配合变量规 ...