非严格次小生成树 pqq的礼物

题目描述

有一天,pqq准备去给×i×准备礼物,他有一些礼品准备包装一下,他用线将这些礼物连在一起,不同的礼物因为风格不同所以连接它们需要不同价值的线。风格差异越大,价格越大(所以两个礼物之间只有一种连接价格),当然有些礼物实在太不友好,所以有些礼物无法相连。pqq打算把所有礼物打包在一起,他不准备花太多钱,但更不想花最少的钱(免得被拒绝)。所以他想知道第二便宜的包装方案(可重复,pqq会认为这是天命并直接选用最小代价来包装礼物),同时,他还想知道最小的包装代价以向×i×进行炫耀。但是由于pqq不够心灵手巧,所以他准备找你来帮他计算答案。

吐槽一下

这个xix是谁?

思考人生

所以这个题就是裸的非严格次小生成树了.
所谓非严格次小生成树,就是满足生成树道路总长 最小生成树的总长且总长最小的那个生成树.
我们不妨思考.

/*
那么这题是有两种写法的.
首先最容易想到的是枚举每一条树边,把这条边去掉重跑最小生成树,复杂度n*m,非常优越.
剩下就是枚举每一条非树边,求这条边连接的两点在树上最大边权,减掉这个加上那个取最小值.
求这个最大边权可以倍增dp,这个我不会,我用了树剖来写,复杂度提升了一个log,不过问题不大.
那么这题便迎刃而解.我太菜了竟然调了一天才写出来.
*/
#include<bits/stdc++.h>
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
  int x=0,f=1;char c=gc();
  for (;!isdigit(c);c=gc()) f^=c=='-';
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return f?x:-x;
  }
template <typename mitsuha>
inline bool read(mitsuha &x){
  x=0;int f=1;char c=gc();
  for (;!isdigit(c)&&~c;c=gc()) f^=c=='-';
  if (!~c) return 0;
  for (;isdigit(c);c=gc()) x=(x<<3)+(x<<1)+(c^'0');
  return x=f?x:-x,1;
  }
template <typename mitsuha>
inline int write(mitsuha x){
  if (!x) return 0&pc(48);
  if (x<0) x=-x,pc('-');
  int bit[20],i,p=0;
  for (;x;x/=10) bit[++p]=x%10;
  for (i=p;i;--i) pc(bit[i]+48);
  return 0;
  }
inline char fuhao(){
  char c=gc();
  for (;isspace(c);c=gc());
  return c;
  }
}using namespace chtholly;
using namespace std;
const int yuzu=2e5;
const ll inf=1e16;
typedef int fuko[yuzu|10];
int n=read(),m=read(),cnt,ecnt;
fuko vis,head;
struct node{
int u,v,cost;
void rd(){u=read(),v=read(),cost=read();}
bool operator <(const node &b){
  return cost<b.cost;
  }
}b[yuzu|10];
struct dsu{
fuko fa;
void init(int n){for (int i=1;i<=n;++i) fa[i]=i;}
int find(int x){return fa[x]^x?fa[x]=find(fa[x]):x;}
int mg(int u,int v){
  int fu=find(u),fv=find(v);
  return fu^fv?fa[fu]=fv,1:0;
  }
}my_;
struct edge{int fr,to,cost,next;}e[yuzu<<1|13];
void add(int u,int v,int c){e[++ecnt]=edge{u,v,c,head[u]},head[u]=ecnt;}
ll mst;
ll getmst(){
for (int i=1;i<=m;++i){
  int u=b[i].u,v=b[i].v,c=b[i].cost;
  if (my_.mg(u,v)){
    vis[i]=1,mst+=c;
    add(u,v,c),add(v,u,c);
    }
  }return mst;
}

namespace tree_chain_splitting{
fuko fa,son,sz,dep,ord,dfn,top,a;

void dfs1(int u,int f){
  sz[u]=1,dep[u]=dep[fa[u]=f]+1; 
  for (int i=head[u];i;i=e[i].next){
    int v=e[i].to;
    if (v^f){
      dfs1(v,u),sz[u]+=sz[v];
      if (sz[v]>sz[son[u]]) son[u]=v; 
      }
    }
  }
void dfs2(int u,int _top){
  top[u]=_top,dfn[ord[++cnt]=u]=cnt;
  if (son[u]) dfs2(son[u],_top);
  for (int i=head[u];i;i=e[i].next){
    int v=e[i].to;
    if (v^fa[u]&&(v^son[u])) dfs2(v,v);
    }
  }

typedef ll karen[yuzu<<2|13];
struct segtree{
#define le rt<<1
#define ri le|1
#define ls le,l,mid
#define rs ri,mid+1,r
karen da;
void build(int rt=1,int l=1,int r=n){
  if (l==r) da[rt]=a[l];
  else{
    int mid=l+r>>1;
    build(ls),build(rs);
    da[rt]=max(da[le],da[ri]);
    }
  }  
ll query(int ql,int qr,int rt=1,int l=1,int r=n){
  if (ql>r||qr<l) return -inf;
  if (ql<=l&&qr>=r) return da[rt];
  int mid=l+r>>1;
  return max(query(ql,qr,ls),query(ql,qr,rs));
  }
}llx;

void preedge(){
  for (int i=1;i<=m;++i) if (vis[i]){
    int u=b[i].u,v=b[i].v;
    if (dep[u]>dep[v]) swap(u,v);
    a[dfn[v]]=b[i].cost;
    }
  }

ll query(int u,int v){
  ll ans=-inf;
  for (;top[u]^top[v];u=fa[top[u]]){
    if (dep[top[u]]<dep[top[v]]) swap(u,v);
    ans=max(ans,llx.query(dfn[top[u]],dfn[u]));
    } 
  if (dep[u]>dep[v]) swap(u,v);
  return max(ans,llx.query(dfn[u]+1,dfn[v]));
  }

int main(){
  int i;
  dfs1(1,0),dfs2(1,1);
  preedge(),llx.build();
  ll zxy=inf;
  for (i=1;i<=m;++i) if (!vis[i]){
    int u=b[i].u,v=b[i].v;
    zxy=min(zxy,mst-query(u,v)+b[i].cost);
    }write(zxy);
  }
}

int main(){
int i,j;
my_.init(n);
for (i=1;i<=m;++i) b[i].rd();
sort(b+1,b+m+1);
write(getmst()),p32;
tree_chain_splitting::main();
}

谢谢大家.

安利一发

倍增写法神仙的博客,学不来.

猜你喜欢

转载自blog.csdn.net/qq_31908675/article/details/81109836