TM终于过了。。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxv 300500
#define maxe 800500
#define inf 0x7fffffffffffffff
using namespace std;
struct edge
{
long long v,w,nxt;
}e[maxe];
struct edge_mp
{
long long u,v,w,flag;
}mp[maxe];
long long n,m,g[maxv],nume=,father[maxv],anc[maxv][],mx1[maxv][],mx2[maxv][],ans=,dx=inf,dis[maxv];
long long r1=,r2=;
bool cmp(edge_mp x,edge_mp y)
{
return x.w<y.w;
}
void addedge(long long u,long long v,long long w)
{
e[++nume].v=v;
e[nume].w=w;
e[nume].nxt=g[u];
g[u]=nume;
}
long long getfather(long long x)
{
if (father[x]!=x)
father[x]=getfather(father[x]);
return father[x];
}
void kruskal()
{
for (long long i=;i<=n;i++) father[i]=i;
sort(mp+,mp+m+,cmp);
for (long long i=;i<=m;i++)
{
long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
if (getfather(u)!=getfather(v))
{
father[getfather(u)]=getfather(v);mp[i].flag=;ans+=w;
addedge(u,v,w);addedge(v,u,w);
}
}
}
void dfs(long long x,long long father)
{
for (long long i=g[x];i;i=e[i].nxt)
{
long long v=e[i].v;
if (v!=father)
{
anc[v][]=x;mx1[v][]=e[i].w;mx2[v][]=;
dis[v]=dis[x]+;
dfs(v,x);
}
}
}
void get_table()
{
for (long long e=;e<=;e++)
for (long long i=;i<=n;i++)
{
anc[i][e]=anc[anc[i][e-]][e-];
long long regis[];
regis[]=mx1[i][e-];regis[]=mx1[anc[i][e-]][e-];
regis[]=mx2[i][e-];regis[]=mx2[anc[i][e-]][e-];
sort(regis+,regis+);
mx1[i][e]=regis[];
for (long long j=;j>=;j--)
{
if (regis[j]==regis[j+]) continue;
else {mx2[i][e]=regis[j];break;}
}
}
} void get_ans(long long x)
{
long long u=mp[x].u,v=mp[x].v;r1=-;r2=-;
long long k1=-,k2=-,k3=-,k4=-;
if (dis[u]<dis[v]) swap(u,v);
if (dis[u]!=dis[v])
{
for (long long e=;e>=;e--)
{
long long pos=anc[u][e];
if ((dis[pos]>=dis[v]) && (pos>))
{
long long regis[];
regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
sort(regis+,regis+);
k1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k2=regis[i];break;}
}
u=pos;
}
}
}
if (u==v)
{
r1=k1;r2=k2;
return;
}
for (long long e=;e>=;e--)
{
long long posu=anc[u][e],posv=anc[v][e];
if (posu!=posv)
{
long long regis[];
regis[]=mx1[u][e];regis[]=mx2[u][e];regis[]=k1;regis[]=k2;
sort(regis+,regis+);
k1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k2=regis[i];break;}
}
regis[]=mx1[v][e];regis[]=mx2[v][e];regis[]=k3;regis[]=k4;
sort(regis+,regis+);
k3=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {k4=regis[i];break;}
}
u=posu;v=posv;
}
}
long long regis[];
regis[]=k1;regis[]=k2;regis[]=k3;regis[]=k4;regis[]=mx1[u][];regis[]=mx1[v][];
sort(regis+,regis+);
r1=regis[];
for (long long i=;i>=;i--)
{
if (regis[i]==regis[i+]) continue;
else {r2=regis[i];break;}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for (long long i=;i<=m;i++)
{
scanf("%lld%lld%lld",&mp[i].u,&mp[i].v,&mp[i].w);
mp[i].flag=;
}
kruskal();
memset(mx1,,sizeof(mx1));
memset(mx2,,sizeof(mx2));
dfs(,);
get_table();
for (long long i=;i<=m;i++)
{
if (mp[i].flag) continue;
long long u=mp[i].u,v=mp[i].v,w=mp[i].w;
get_ans(i);
if (r1==mp[i].w)
{
if (r2==-) continue;
dx=min(dx,mp[i].w-r2);
}
else if (r1<mp[i].w) dx=min(dx,mp[i].w-r1);
}
printf("%lld\n",ans+dx);
return ;
}

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

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

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

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

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

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

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

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

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

  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 严格次小生成树

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

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

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

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

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

随机推荐

  1. Runtime的用法

    public class RuntimeTest { public static void main(String[] args) { Runtime run =Runtime.getRuntime( ...

  2. HDU 2709 Sumsets(递推)

    Sumsets http://acm.hdu.edu.cn/showproblem.php?pid=2709 Problem Description Farmer John commanded his ...

  3. 重载和覆盖的区别?(overload vs override)

    override与overload的区别? override 表示重写,overload 表示重载.override是子类和父类之间的关系,是垂直关系:overload是同一个类中方法之间的关系,是水 ...

  4. hdu 4745 Two Rabbits

    思路:求最长回文子串的长度!代码如下: #include<iostream> #include<stdio.h> #include<algorithm> #incl ...

  5. spring_150804_controller

    实体类: package com.spring.model; public class DogPet { private int id; private String name; private in ...

  6. MongoDB (三) MongoDB 安装

    MongoDB安装在Windows上 在 Windows上,首先要安装 MongoDB下载最新发布的MongoDB: http://www.mongodb.org/downloads 确保得到正确的版 ...

  7. C# Socket 入门4 UPD 发送结构体(转)

    今天我们来学 socket  发送结构体 1. 先看要发送的结构体 using System; using System.Collections.Generic; using System.Text; ...

  8. Linux command: usermod -- 改变用户状态

    应用举例: 1. usermod -g newuser newuser force use GROUP as new primary group. 一般时候是默认的,也是必须的(不能更改).2. 指定 ...

  9. CentOS 配置vncserver

    一.安装 以root用户运行以下命令来安装vncserver; yum install tigervnc-server 同样运行以下命令来安装vncviewer; yum install vnc 停止 ...

  10. Java:网络编程之IP、URL

    java.net  类 InetAddress 此类表示互联网协议 (IP) 地址. 会抛出异常 UnknownHostException   直接已知子类:         Inet4Address ...