话说这个[BeiJing2010组队]是个什喵玩意?

这是一道严格次小生成树,而次小生成树的做法是层出不穷的

MATO IS NO.1 的博客里对两种算法都有很好的解释,值得拥有:  (果然除我以外,所有自称傻 X 的都是神犇喵~)

  http://www.cppblog.com/MatoNo1/archive/2011/05/29/147627.aspx

MATO还讲了一个神级复杂度的次小生成树:  (请全部读完。如果被坑,后果自负)

  http://www.cppblog.com/MatoNo1/archive/2011/11/16/149812.html

如果你可以打开人人网的话(你懂的喵~),这也是篇很好的博文:

  http://blog.renren.com/share/235365847/6633394303

该说的都在上面了,我就扔扔代码吧  (高能勿喷)

 #include <cstdio>
#include <algorithm>
typedef long long llint;
const int inf=0x7FFFFFFF;
const int sizeOfN=;
const int sizeOfM=; namespace IOspace
{
inline int getint()
{
register int num=;
register char ch;
do ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
return num;
}
inline void putint(llint num, char ch='\n')
{
char stack[];
register int top=;
if (num==) stack[top=]='';
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
if (ch) putchar(ch);
}
} int N, M; struct node {int u, v, c;};
node a[sizeOfM];
bool b[sizeOfM];
inline bool operator < (node i, node j)
{return i.c<j.c;} struct edge {int point, dist; edge * next;};
edge MEM[sizeOfM], * PORT=MEM;
edge * E[sizeOfN];
inline edge * newedge(int _point, int _dist, edge * _next)
{edge * ret=PORT++; ret->point=_point; ret->dist=_dist; ret->next=_next; return ret;}
inline void build(int u, int v, int c)
{E[u]=newedge(v, c, E[u]); E[v]=newedge(u, c, E[v]);} int r[sizeOfN];
int find(int x) {return r[x]==x?x:r[x]=find(r[x]);} int f[sizeOfN][], l[][sizeOfN][], h[sizeOfN];
bool vis[sizeOfN];
int top, stack[sizeOfN]; edge * temp[sizeOfN];
inline void search(); inline int max(int x, int y) {return x>y?x:y;}
inline int min(int x, int y) {return x<y?x:y;}
inline void swap(int & x, int & y) {int t=x; x=y; y=t;}
inline int lg(int x) {int i; for (i=;x>;i++) x>>=; return i;}
inline int lowbit(int x) {return x & -x;}
inline int lca(int, int, int);
inline llint kurskal();
inline void prepare();
inline int calc(); int main()
{
llint ans=; N=IOspace::getint(); M=IOspace::getint();
for (int i=;i<M;i++) a[i].u=IOspace::getint(), a[i].v=IOspace::getint(), a[i].c=IOspace::getint(); ans=kurskal();
prepare();
ans+=calc(); IOspace::putint(ans); return ;
}
inline void search()
{
f[][]=; h[]=;
for (stack[++top]=, temp[top]=E[];top; )
{
int & u=stack[top]; edge *& i=temp[top];
if (!vis[u]) vis[u]=;
for ( ;i;i=i->next) if (!vis[i->point])
{
f[i->point][]=u; h[i->point]=h[u]+;
l[][i->point][]=i->dist; l[][i->point][]=-inf;
stack[++top]=i->point; temp[top]=E[i->point];
break;
}
if (i) continue;
top--;
}
}
inline llint kurskal()
{
llint ret=;
int tot=N-; std::sort(a, a+M);
for (int i=;i<=N;i++) r[i]=i; for (int i=;i<M;i++)
{
int u=find(a[i].u), v=find(a[i].v);
if (u!=v)
{
build(a[i].u, a[i].v, a[i].c); ret+=a[i].c;
b[i]=;
r[u]=v;
if (!--tot) break;
}
} return ret;
}
inline void prepare()
{
search();
for (int j=;j<;j++)
for (int i=;i<=N;i++) if (h[i]>=(<<j))
{
f[i][j]=f[f[i][j-]][j-];
l[][i][j]=l[][i][j-]; l[][i][j]=l[][i][j-];
if (l[][f[i][j-]][j-]>l[][i][j]) l[][i][j]=l[][i][j], l[][i][j]=l[][f[i][j-]][j-];
else if (l[][f[i][j-]][j-]<l[][i][j])
if (l[][f[i][j-]][j-]>l[][i][j]) l[][i][j]=l[][f[i][j-]][j-];
}
}
inline int lca(int u, int v, int x)
{
int ret=-, dis; if (h[u]<h[v]) swap(u, v);
while (dis=h[u]-h[v])
{
int up=lg(lowbit(dis));
ret=max(ret, l[l[][u][up]==x][u][up]);
u=f[u][up];
}
if (u==v) return ret; for (int i=;i>=;i--)
if (f[u][i]!=f[v][i])
{
ret=max(ret, l[l[][u][i]==x][u][i]);
ret=max(ret, l[l[][v][i]==x][v][i]);
u=f[u][i]; v=f[v][i];
}
ret=max(ret, l[l[][u][]==x][u][]);
ret=max(ret, l[l[][v][]==x][v][]); return ret;
}
inline int calc()
{
int ret=inf;
for (int i=;i<M;i++)
if (!b[i])
ret=min(ret, a[i].c-lca(a[i].u, a[i].v, a[i].c));
return ret;
}

本傻装B系列

写的比树套树还长,真是没脸见人了喵~

[BeiJing2010组队][BZOJ 1977]次小生成树 Tree的更多相关文章

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

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

  2. BZOJ 1977 次小生成树

    TM终于过了.... #include<iostream> #include<cstdio> #include<cstring> #include<algor ...

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

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

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

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

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

    1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 5168  Solved: 1668[S ...

  6. 【BZOJ1977】[BeiJing2010组队]次小生成树 Tree 最小生成树+倍增

    [BZOJ1977][BeiJing2010组队]次小生成树 Tree Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C ...

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

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

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

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

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

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

随机推荐

  1. C语言中的getchar和putchar详解

    首先给出<The_C_Programming_Language>这本书中的例子: #include <stdio.h> int main(){    int c;     c ...

  2. Repeater 合并单元格

    前途页面: <asp:Repeater ID="rptList" runat="server" OnPreRender="rptList_Pre ...

  3. SharePoint 2013 Nintex Workflow 工作流帮助(八)

    博客地址 http://blog.csdn.net/foxdave 工作流动作 15. Complete Workflow Task(User interaction分组) 此工作流动作将完成任何进行 ...

  4. JavaScript:变量对象(Variable Object)

    引言:在使用JavaScript编程的时候,避免不了声明函数和变量,但是我们很少知道解释器是如何并且在什么地方找到这些函数和变量的,我们在引用这些对象的时候究竟发生了什么? 对ECMAScript程序 ...

  5. 根据username查找user

    返回的是一个list<User>,不过验证密码的时候,要求返回是一个user对象,如果用uniqueresult,这个是过时的方法,如果用getResultList 会得到一个列表,get ...

  6. 有关PHP的字符串知识

    字符串是由一系列字符组成,在PHP中,字符和字节一样,也就是说,一共有256种不同字符的可能性. 字符串型可以用三种方法定义:单引号形式.双引号形式和Heredoc结构形式. 1.每条指令可要记得使用 ...

  7. 《AppletButtonEvent.java》

    //AppletButtonEvent.java import java.applet.*; import java.awt.*; import java.awt.event.*; public cl ...

  8. hdu 2022

    Ps:麻蛋...第一次想得太复杂了..用字符串组来存.越弄越傻逼...后来用int就行了... 代码: #include "stdio.h"#include "stdli ...

  9. 链表操作----将单链表向右旋转 K 个位置

    给定一个单链表,设计一个算法实现链表向右旋转 K 个位置. 举例: 给定 1->2->3->4->5->6->NULL, K=3 则     4->5-> ...

  10. 【Tsinghua OJ】循环移位(Cycle)

    Description Cycle shifting refers to following operation on the sting. Moving first letter to the en ...