2018.09.15 秘密的牛奶管道SECRET(次小生成树)
描述
约翰叔叔希望能够廉价连接他的供水系统,但是他不希望他的竞争对手知道他选择的路线。一般这样的问题需要选择最便宜的方式,所以他决定避免这种情况而采用第二便宜的方式。
现在有W(3 <= W <= 2000)个供水站,其中最多有P(P <=20,000)< span=”“>条管道,每一条管道连接了两个水站,并且不存在一条管道连接同一个水站,两个水站之间最多只有一条管道。每条管道有一定的费用。请寻找第二便宜的连接方式,使所有的水站相连。
假设最便宜的方案有且只有一种,并且至少有两种可行的连接方案。所有的费用都不超过16位有符号整数。水站用1到W的自然数表示
输入
第一行:两个数W和P 第2~P+1行:每行描述了一条管道,有3个用空格分开的整数,前两个数表示管道连接的两个端点。第3个数是管道的费用
输出
仅一行,第二便宜的管道铺设费用
样例输入
5 7
1 2 3
2 3 4
1 4 7
2 4 11
2 5 9
5 4 5
3 5 8
样例输出
20
标签
USACO2002-OPEN-GREEN
自己yy了一个次小生成树的写法。
就是每次用一个 不在次小生成树中的边去更新答案。
代码:
#include<bits/stdc++.h>
#define N 100005
#define M 300005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
#define ll long long
#define xx first
#define yy second
using namespace std;
inline ll read(){
ll ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int first[N],cnt=0,n,m,sizz=0,Fa[N],fa[N],hson[N],dep[N],siz[N],top[N],num[N],pred[N];
bool vis[M];
ll sum=0,ans=1e18,a[N];
struct edge{int v,next;ll w;}e[N<<1];
struct Edge{int u,v;ll w;}t[M];
struct Node{int l,r;ll mx,sx;}T[N<<2];
inline bool cmp(Edge a,Edge b){return a.w<b.w;}
inline int find(int x){return x==Fa[x]?Fa[x]:Fa[x]=find(Fa[x]);}
inline void add(int u,int v,ll w){e[++cnt].v=v,e[cnt].w=w,e[cnt].next=first[u],first[u]=cnt;}
inline void kruskal(){
int tot=0;
for(int i=1;i<=n;++i)Fa[i]=i;
sort(t+1,t+m+1,cmp);
for(int i=1;i<=m;++i){
if(tot==n-1)break;
int fx=find(t[i].u),fy=find(t[i].v);
if(fx!=fy)vis[i]=true,Fa[fx]=fy,sum+=t[i].w,++tot,add(t[i].u,t[i].v,t[i].w),add(t[i].v,t[i].u,t[i].w);
}
}
inline void dfs1(int p){
siz[p]=1;
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa[p])continue;
dep[v]=dep[p]+1,fa[v]=p,a[v]=e[i].w,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
inline void dfs2(int p,int tp){
top[p]=tp,pred[num[p]=++sizz]=p;
if(!hson[p])return;
dfs2(hson[p],tp);
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa[p]||v==hson[p])continue;
dfs2(v,v);
}
}
inline ll max(ll a,ll b){return a>b?a:b;}
inline void pushup(int p){
T[p].mx=max(T[lc].mx,T[rc].mx);
T[p].sx=max(T[p].mx==T[lc].mx?T[lc].sx:T[lc].mx,T[p].mx==T[rc].mx?T[rc].sx:T[rc].mx);
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r){T[p].mx=a[pred[l]],T[p].sx=-1;return;}
build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline pair<ll,ll> query(int p,int ql,int qr){
if(T[p].r<ql||T[p].l>qr)return make_pair(0,-1);
if(ql<=T[p].l&&T[p].r<=qr)return make_pair(T[p].mx,T[p].sx);
if(qr<=mid)return query(lc,ql,qr);
if(ql>mid)return query(rc,ql,qr);
pair<ll,ll>ans1=query(lc,ql,mid),ans2=query(rc,mid+1,qr),ans;
ans.xx=max(ans1.xx,ans2.xx);
ans.yy=max(ans1.xx==ans.xx?ans1.yy:ans1.xx,ans2.xx==ans.xx?ans2.yy:ans2.xx);
return ans;
}
inline pair<ll,ll> ask(int x,int y){
pair<ll,ll>ret=make_pair(0,-1),tmp1,tmp2;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])x^=y,y^=x,x^=y;
tmp1=query(1,num[top[x]],num[x]),tmp2=ret;
ret.xx=max(tmp1.xx,tmp2.xx);
ret.yy=max(ret.xx==tmp1.xx?tmp1.yy:tmp1.xx,ret.xx==tmp2.xx?tmp2.yy:tmp2.xx);
x=fa[top[x]];
}
if(dep[x]<dep[y])x^=y,y^=x,x^=y;
tmp1=query(1,num[y]+1,num[x]),tmp2=ret;
ret.xx=max(tmp1.xx,tmp2.xx);
ret.yy=max(ret.xx==tmp1.xx?tmp1.yy:tmp1.xx,ret.xx==tmp2.xx?tmp2.yy:tmp2.xx);
return ret;
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;++i)t[i].u=read(),t[i].v=read(),t[i].w=read();
kruskal(),dfs1(1),dfs2(1,1),build(1,1,n);
for(int i=1;i<=m;++i){
if(vis[i])continue;
int u=t[i].u,v=t[i].v;
ll w=t[i].w;
pair<ll,ll>tmp=ask(u,v);
if(w!=tmp.xx)ans=min(ans,sum-tmp.xx+w);
else if(tmp.yy!=-1)ans=min(ans,sum-tmp.yy+w);
}
cout<<ans;
return 0;
}
2018.09.15 秘密的牛奶管道SECRET(次小生成树)的更多相关文章
- 「LOJ#10068」「一本通 3.1 练习 3」秘密的牛奶运输(次小生成树
题目描述 Farmer John 要把他的牛奶运输到各个销售点.运输过程中,可以先把牛奶运输到一些销售点,再由这些销售点分别运输到其他销售点. 运输的总距离越小,运输的成本也就越低.低成本的运输是 F ...
- Lean Data Innovation Sharing Salon(2018.09.15)
时间:2018.09.15地点:北京国华投资大厦
- 2018.09.15模拟总结(T1,T3)
过了一周,终于迎来了第二次模拟(这不是期待的语气),看第一周毒瘤程度,我就觉得接下来的模拟只能更毒瘤. 花了10多分钟读完了三道题,觉得暴力还是挺好写的,然后在每一道题都思索那么几分钟后,觉得还是写暴 ...
- 2018.09.15点名器(简单dp)
描述 Ssoier在紧张的学习中,杜老师每天给他们传授精妙的知识. 杜老师为了活跃气氛,设计了一个点名器,这个点名器包含一个长度为M的数组(下标1开始),每个元素是一个oier的名字,每次点名的时候, ...
- 2018.09.15 poj1734Sightseeing trip(floyd求最小环)
跟hdu1599差不多.. 只是需要输出方案. 这个可以递归求解. 代码: #include<iostream> #include<cstdio> #include<cs ...
- 2018.09.15 hdu1599find the mincost route(floyd求最小环)
传送门 floyd求最小环的板子题目. 就是枚举两个相邻的点求最小环就行了. 代码: #include<bits/stdc++.h> #define inf 0x3f3f3f3f3f3f ...
- 2018.09.15 bzoj1977:次小生成树 Tree(次小生成树+树剖)
传送门 一道比较综合的好题. 由于是求严格的次小生成树. 我们需要维护一条路径上的最小值和次小值. 其中最小值和次小值不能相同. 由于不喜欢倍增我选择了用树链剖分维护. 代码: #include< ...
- 2018.09.15 vijos1053Easy sssp(最短路)
传送门 貌似可以最短路时同时判定负环啊. 但我不想这样做. 于是写了一个dfs版的判环,bfs版的求最短路. 代码: #include<iostream> #include<ccty ...
- 2018.09.15 hdu3018Ant Trip(欧拉路)
传送门 显然答案等于各个连通分量的笔画数之和. 因此我们dfs每个连通分量计算对答案的贡献. 对于一个连通分量,如果本来就有欧拉回路那么只需要一笔. 否则需要寄点数/2那么多笔才能画完. 知道这个结论 ...
随机推荐
- Simple2D-25 精灵动作
精灵动画作用在精灵上,使精灵表现出动画效果.本文将详细说明如何创建一个简单的动作系统,暂时只有 4 中基本的动作——平移.旋转.缩放和 Alpha 变化,并且这些动作能够自由组合,组成串行动作或并行动 ...
- NDK开发中的一个HTTP下载实例附带下载进度
有一个控制下载的管理类吧,调用http下载类进行各种下载,同时在下载过程中可以显示其下载的进度,而且在每个下载结束之后以类似回调的方式告诉管理类,以继续进行后续的操作. 直接代码: .h文件 #pra ...
- VC 判断网络连接函数
IsNetworkAlive Bool IsNetworkAlive( _Out_ LPDWORD lpdwFlags ); Header Sensapi.h Library Sensapi.lib ...
- 通过maven 上传jar 到nexus3,cong nexus3下载jar
nexus是一种常见的maven私服软件. 网上介绍的都是nexus2的使用,下面是最新版nexus3的使用方式. 首先需要从官网下载nexus3的包,很卡. 下载好以后解压会有两个文件夹:nexus ...
- one by one 项目 part 3
mysql error:Table 'performance_schema.session_variables' doesn't exist 打开cmd 输入:mysql_upgrade -u roo ...
- java 可伸缩阻塞队列实现
最近一年多写的最虐心的代码.必须好好复习java并发了.搞了一晚上终于测试都跑通过了,特此纪念,以资鼓励! import java.util.ArrayList; import java.util.L ...
- (转)游戏引擎中三大及时光照渲染方法介绍(以unity3d为例)
重要:在目前市面上常见的游戏引擎中,主要采用以下三种灯光实现方式: 顶点照明渲染路径细节 Vertex Lit Rendering Path Details 正向渲染路径细节 Forward Rend ...
- js中定时器之一
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- 断开的管道 java.io.IOException: Broken pipe 解决方法
一.Broken pipe产生原因分析 1.当访问某个服务突然服务器挂了,就会产生Broken pipe; 2.客户端读取超时关闭了连接,这时服务器往客户端再写数据就发生了broken pipe异常! ...
- conductor Workflow Metrics
Server Metrics conductor使用spectator收集指标.https://github.com/Netflix/spectator 名称 目的 标签 workflow_serve ...