河童重工,恐怖如斯

news/2025/2/8 19:25:39/文章来源:https://www.cnblogs.com/BYR-KKK/p/18705243

显然是 Boruvka,考虑一次怎么求边。

一棵树的时候是简单的,树形 dp 即可。考虑第二棵树是菊花怎么做,显然这个问题等价于完全图上的边权形如 \(D(x,y)+a_x+a_y\),这也是简单的,推广这个做法,对第二棵树点分治,每次对不同子树中的点统计贡献,这样每个点就有了两个属性(原图上的颜色、第二棵树上所在的子树),不妨分别记为 \(col_i\)\(bel_i\),那我们就是要找两个 \(bel_i\neq bel_j\)\(col_i\neq col_j\) 的点。多记一下状态大力分类讨论转移可以解决。考虑是否真要这么麻烦呢?如果我们不区分 \(bel_i\),考虑两个点 \((i,j)\),他们可能会在点分治时产生贡献,但一定不是最优,考虑两者在不同子树一定比当前优,因此无需考虑区分 \(bel_i\)

还有一个问题就是如果每次点分治时都对原树做一遍 dp,复杂度为 \(O(n^2)\)。考虑点分治时只会有 \(O(n\log n)\) 个点有用,因此只需对其建虚树即可,可以做到 \(O(n\log^3 n)\),由于每次做 Boruvka 的时候虚树形态相同,因此可以提前预处理出来。时间复杂度 \(O(n\log^2 n)\)

代码里面有份暴力,所以看上去比较长。

#include<bits/stdc++.h>
namespace brute_force{
// #include<bits/stdc++.h>
#define int long long
#define fi first
#define se second
#define pii std::pair<int,int>
#define vint std::vector<int>
#define vpair std::vector<pii>
#define debug(...) fprintf(stderr,##__VA_ARGS__)template<typename T>
void read(T &x){x=0;int f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar();x*=f;
}std::stack<char>st;
template<typename T>
void print(T x){if(x==0) putchar('0');if(x<0) putchar('-'),x=-x;while(st.size()) st.pop();while(x) st.push((char)('0'+x%10)),x/=10;while(st.size()) putchar(st.top()),st.pop();
}template<typename T>
void printsp(T x){print(x),putchar(' ');
}template<typename T>
void println(T x){print(x),putchar('\n');
}template<typename T,typename I>
bool chkmin(T &a,I b){if(a>b) return a=b,1;return 0;
}template<typename T,typename I>
bool chkmax(T &a,I b){if(a<b) return a=b,1;return 0;
}template<typename T,typename I>
void addedge(std::vector<I>*vec,T u,T v){vec[u].push_back(v);
}template<typename T,typename I,typename K>
void addedge(std::vector<K>*vec,T u,T v,I w){vec[u].push_back({v,w});
}template<typename T,typename I>
void addd(std::vector<I>*vec,T u,T v){addedge(vec,u,v),addedge(vec,v,u);
}template<typename T,typename I,typename K>
void addd(std::vector<K>*vec,T u,T v,I w){addedge(vec,u,v,w),addedge(vec,v,u,w);
}bool Mbe;const int inf=1e18,MOD1=998244353,MOD2=1e9+7;const int maxn=1e3+10;vpair a[maxn],b[maxn],c[maxn];int n,dis1[maxn],dis2[maxn],f[maxn][20],g[maxn][20],dep1[maxn],dep2[maxn];struct edge{int u,v,w;
}d[maxn*maxn];namespace DSU{int to[maxn];void init_(){for(int i=1;i<=n;i++) to[i]=i;}int go(int x){if(to[x]==x) return x;return to[x]=go(to[x]);}bool merge(int x,int y){x=go(x),y=go(y);if(x==y) return 0;to[x]=y;return 1;}
}using namespace DSU;void dfs1(int p,int fa){dep1[p]=dep1[fa]+1;f[p][0]=fa;for(pii i:a[p]){if(i.fi==fa) continue;dis1[i.fi]=dis1[p]+i.se;dfs1(i.fi,p);}
}void dfs2(int p,int fa){dep2[p]=dep2[fa]+1;g[p][0]=fa;for(pii i:b[p]){if(i.fi==fa) continue;dis2[i.fi]=dis2[p]+i.se;dfs2(i.fi,p);}
}edge made(int u,int v,int w){edge res;res.u=u,res.v=v,res.w=w;return res;
}void init(){for(int j=1;j<=19;j++)for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1],g[i][j]=g[g[i][j-1]][j-1];
}int lca1(int x,int y){if(dep1[x]<dep1[y]) std::swap(x,y);for(int i=19;i>=0;i--)if(dep1[f[x][i]]>=dep1[y]) x=f[x][i];if(x==y) return x;for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];return f[x][0];
}int lca2(int x,int y){if(dep2[x]<dep2[y]) std::swap(x,y);for(int i=19;i>=0;i--)if(dep2[g[x][i]]>=dep2[y]) x=g[x][i];if(x==y) return x;for(int i=19;i>=0;i--)if(g[x][i]!=g[y][i]) x=g[x][i],y=g[y][i];return g[x][0];
}bool cmp(edge s1,edge s2){return s1.w<s2.w;
}bool Men;void main(){debug("%.6lfMB\n",(&Mbe-&Men)/1048576.0);read(n);int x,y,v;#define sb(a) read(x),read(y),read(v),addd(a,x,y,v)for(int i=1;i<n;i++) sb(a);for(int i=1;i<n;i++) sb(b);dfs1(1,0),dfs2(1,0),init();int cnt=0;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){int cost=dis1[i]+dis1[j]-2*dis1[lca1(i,j)]+dis2[i]+dis2[j]-2*dis2[lca2(i,j)];// addd(a,i,j,cost);d[++cnt].u=i,d[cnt].v=j,d[cnt].w=cost;}init_();std::sort(d+1,d+cnt+1,cmp);int cost=0;std::vector<edge>vec;for(int i=1;i<=cnt;i++){int u=d[i].u,v=d[i].v,w=d[i].w;if(!merge(u,v)) continue;cost+=w;vec.push_back(made(u,v,w));// addd(c,u,v);}println(cost);for(edge i:vec) printf("%lld %lld %lld\n",i.u,i.v,i.w);// for(int i=1;i<=n;i++)// for(int j:vost)debug("%.6lfms\n",1e3*clock()/CLOCKS_PER_SEC);
}}
#define int long long
#define fi first
#define se second
#define pii std::pair<int,int>
#define vint std::vector<int>
#define vpair std::vector<pii>
#define debug(...) fprintf(stderr,##__VA_ARGS__)template<typename T>
void read(T &x){x=0;int f=1;char c=getchar();while(c<'0'||c>'9'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9') x=x*10+(int)(c-'0'),c=getchar();x*=f;
}std::stack<char>st;
template<typename T>
void print(T x){if(x==0) putchar('0');if(x<0) putchar('-'),x=-x;while(st.size()) st.pop();while(x) st.push((char)('0'+x%10)),x/=10;while(st.size()) putchar(st.top()),st.pop();
}template<typename T>
void printsp(T x){print(x),putchar(' ');
}template<typename T>
void println(T x){print(x),putchar('\n');
}template<typename T,typename I>
bool chkmin(T &a,I b){if(a>b) return a=b,1;return 0;
}template<typename T,typename I>
bool chkmax(T &a,I b){if(a<b) return a=b,1;return 0;
}template<typename T,typename I>
void addedge(std::vector<I>*vec,T u,T v){vec[u].push_back(v);
}template<typename T,typename I,typename K>
void addedge(std::vector<K>*vec,T u,T v,I w){vec[u].push_back({v,w});
}template<typename T,typename I>
void addd(std::vector<I>*vec,T u,T v){addedge(vec,u,v),addedge(vec,v,u);
}template<typename T,typename I,typename K>
void addd(std::vector<K>*vec,T u,T v,I w){addedge(vec,u,v,w),addedge(vec,v,u,w);
}bool Mbe;const int inf=1e18,MOD1=998244353,MOD2=1e9+7;const int maxn=1e5+10;int n,num,sz[maxn],mx[maxn],dfn[maxn],edfn[maxn*2],cnt,tot,fir[maxn],fdfn[maxn],mt[maxn*2][18],lg[maxn*2],dis[maxn],bel[maxn],val[maxn],best[maxn],sec[maxn],bcol[maxn],seccol[maxn];bool vis[maxn];vint col[maxn],vec;vpair a[maxn],b[maxn],mst;struct edge{int u,v,w;
};edge newedge(int u,int v,int w){edge res;res.u=u,res.v=v,res.w=w;return res;
}struct Tree{int rt;std::vector<edge>a;
}dot[maxn];namespace LCA{void dfs(int p,int fa){dfn[p]=++cnt,edfn[++tot]=dfn[p];fir[p]=tot,fdfn[cnt]=p;for(pii i:a[p]){if(i.fi==fa) continue;dis[i.fi]=dis[p]+i.se;dfs(i.fi,p);edfn[++tot]=dfn[p];}}void init(){dfs(1,0);for(int i=1;i<=tot;i++) mt[i][0]=edfn[i];for(int j=1;j<20;j++)for(int i=1;i+(1ll<<j)-1<=tot;i++) mt[i][j]=std::min(mt[i][j-1],mt[i+(1ll<<(j-1))][j-1]);lg[0]=-1;for(int i=1;i<=tot;i++) lg[i]=lg[i>>1]+1;}int query(int l,int r){if(l>r) std::swap(l,r);int len=r-l+1;return std::min(mt[l][lg[len]],mt[r-(1ll<<lg[len])+1][lg[len]]);}int lca(int x,int y){return fdfn[query(fir[x],fir[y])];}
}void pdfs(int p,int fa){vec.push_back(p);sz[p]=1;mx[p]=0;for(pii i:b[p]){if(i.fi==fa||vis[i.fi]) continue;pdfs(i.fi,p);sz[p]+=sz[i.fi];chkmax(mx[p],sz[i.fi]);}// debug("p=%lld sz=%lld mx=%lld\n",p,sz[p],mx[p]);
}int zx,siz;void findrt(int p,int fa,int gt){// debug("p=%lld gt=%lld mx=%llld siz=%lld\n",p,gt,mx[p],siz);;if(std::max(gt,mx[p])<siz) zx=p,siz=std::max(gt,mx[p]);for(pii i:b[p]){if(i.fi==fa||vis[i.fi]) continue;findrt(i.fi,p,gt+sz[p]-sz[i.fi]);}
}bool cmp_dfn(int x,int y){return dfn[x]<dfn[y];
}void dfs(int p){vec.clear();siz=inf;pdfs(p,0),findrt(p,0,0);vint nd;// debug("zx=%lld\n",zx);std::sort(vec.begin(),vec.end(),cmp_dfn);// for(int i:vec) debug("i=%lld\n",i);for(int i=1;i<vec.size();i++){int lca=LCA::lca(vec[i],vec[i-1]);nd.push_back(lca);// debug("%lld %lld lca:%lld\n",vec[i],vec[i-1],lca);// dot[zx].a.push_back(newedge(vec[i],lca,dis[vec[i]]-dis[lca]));// debug("%lld - %lld > %lld\n",vec[i],lca,dis[vec[i]]-dis[lca]);	// debug("zx=%lld %lld %lld\n",zx,vec[i])}for(int i:nd) vec.push_back(i);std::sort(vec.begin(),vec.end(),cmp_dfn);auto z=std::unique(vec.begin(),vec.end());auto i=vec.begin();int las=*i;i++;for(;i!=z;i++){int now=*i;int lca=LCA::lca(las,now);dot[zx].a.push_back(newedge(now,lca,dis[now]-dis[lca]));// debug("%lld - %lld > %lld\n",now,lca,dis[now]-dis[lca]);las=now;}int mi=inf;for(int i:vec) if(chkmin(mi,dfn[i])) dot[zx].rt=i;vis[zx]=1;for(pii i:b[zx]) if(!vis[i.fi]) dfs(i.fi);
}int cost;namespace DSU{int to[maxn];void init(){for(int i=1;i<=n;i++) to[i]=i;}int go(int p){if(to[p]==p) return p;return to[p]=go(to[p]);}void merge(int x,int y){x=go(x),y=go(y);if(x==y) return ;to[x]=y;}
}int ok[maxn],tim;namespace getMST{int sz[maxn],mx[maxn],zx,siz,cho[maxn],id[maxn];bool vis[maxn];vpair c[maxn];namespace VT{void dfs(int p,int fa){for(pii i:c[p]){if(i.fi==fa) continue;dfs(i.fi,p);}if(ok[p]!=tim) val[p]=inf;best[p]=val[p],bcol[p]=bel[p];sec[p]=inf,seccol[p]=0;for(pii i:c[p]){if(i.fi==fa) continue;if(best[i.fi]+i.se<=best[p]){if(bcol[i.fi]==bcol[p]) best[p]=best[i.fi]+i.se;else sec[p]=best[p],seccol[p]=bcol[p],best[p]=best[i.fi]+i.se,bcol[p]=bcol[i.fi];}else if(best[i.fi]+i.se<=sec[p]&&bcol[p]!=bcol[i.fi]){sec[p]=best[i.fi]+i.se,seccol[p]=bcol[i.fi];}if(sec[i.fi]+i.se<=sec[p]&&seccol[i.fi]!=bcol[p]) sec[p]=sec[i.fi]+i.se,seccol[p]=seccol[i.fi];}// best[p]+=val[p],sec[p]+=val[p];// debug("p=%lld best=%lld bcol=%lld sec=%lld seccol=%lld\n",p,best[p],bcol[p],sec[p],seccol[p]);}void pdfs(int p,int fa,int bst,int snd,int bstcol,int sndcol){int w=inf;if(bel[p]!=bcol[p]) chkmin(w,best[p]);if(bstcol!=bel[p]) chkmin(w,bst);if(bel[p]!=seccol[p]) chkmin(w,sec[p]);if(bel[p]!=sndcol) chkmin(w,snd);if(chkmin(cho[bel[p]],w+val[p])){if(w==best[p]&&bcol[p]!=bel[p]) id[bel[p]]=bcol[p];else if(w==bst&&bstcol!=bel[p]) id[bel[p]]=bstcol;else if(w==snd&&sndcol!=bel[p]) id[bel[p]]=sndcol;else id[bel[p]]=seccol[p];}// debug("p=%lld bst=%lld snd=%lld bstcol=%lld sndcol=%lld w=%lld cho=%lld id=%lld\n",p,bst,snd,bstcol,sndcol,w,cho[bel[p]],id[bel[p]]);int bw=std::min(std::min(std::min(bst,snd),best[p]),sec[p]),bc;int cw=inf,cc;if(bw==best[p]) bc=bcol[p];else bc=bstcol;if(snd<cw&&sndcol!=bc) cw=snd,cc=sndcol;if(sec[p]<cw&&seccol[p]!=bc) cw=sec[p],cc=seccol[p];// if(cw==snd) cc=sndcol;// else cc=seccol[p];if(bw==best[p]&&bcol[p]!=bstcol&&bst<cw) cw=bst,cc=bstcol;if(bw==bst&&bstcol!=bcol[p]&&best[p]<cw) cw=best[p],cc=bcol[p];for(pii i:c[p]){if(i.fi==fa) continue;pdfs(i.fi,p,bw+i.se,cw+i.se,bc,cc);}}}void pdfs(int p,int fa){sz[p]=1,mx[p]=0,ok[p]=tim;for(pii i:b[p]){if(i.fi==fa||vis[i.fi]) continue;pdfs(i.fi,p);sz[p]+=sz[i.fi];chkmax(mx[p],sz[i.fi]);}}void findrt(int p,int fa,int gt){if(chkmin(siz,std::max(mx[p],gt))) zx=p;for(pii i:b[p]){if(i.fi==fa||vis[i.fi]) continue;;findrt(i.fi,p,gt+sz[p]-sz[i.fi]);}}void getval(int p,int fa){for(pii i:b[p]){if(i.fi==fa||vis[i.fi]) continue;val[i.fi]=val[p]+i.se;// debug("i.fi=%lld val=%lld p=%lld i.se=%lld\n",i.fi,val[i.fi],p,i.se);getval(i.fi,p);}}void dfs(int p){tim++;siz=inf;pdfs(p,0),findrt(p,0,0);p=zx;// debug("zx=%lld\n",zx);val[p]=0,getval(p,0);for(edge i:dot[p].a){addd(c,i.u,i.v,i.w);}VT::dfs(dot[p].rt,0),VT::pdfs(dot[p].rt,0,inf,inf,-1,-1);for(edge i:dot[p].a) c[i.u].clear(),c[i.v].clear();vis[zx]=1;for(pii i:b[p]){if(vis[i.fi]) continue;dfs(i.fi);}}int to[maxn];void Boruvka(){// debug("ok\n");// DSU::init();for(int i=1;i<=n;i++)for(int j:col[i]) bel[j]=i,cho[i]=inf,id[i]=i;//,debug("i=%lld j=%lld\n",i,j);memset(vis,0,sizeof(vis));dfs(1);for(int i=1;i<=n;i++){if(!col[i].size()) continue;if(DSU::go(i)==DSU::go(id[i])) continue;// if(id[i]<i) continue;cost+=cho[i];num--;DSU::merge(i,id[i]);// for(int j:col[id[i]]) col[i].push_back(j);}for(int i=1;i<=n;i++) col[i].clear();for(int i=1;i<=n;i++) col[DSU::go(i)].push_back(i);}
}bool Men;signed main(){// freopen("data.in","r",stdin),freopen("my.out","w",stdout);// brute_force::main();// return 0;debug("%.6lfMB\n",(&Mbe-&Men)/1048576.0);read(n);for(int i=1;i<n;i++){int x,y,v;read(x),read(y),read(v);addd(a,x,y,v);}LCA::init();for(int i=1;i<n;i++){int x,y,v;read(x),read(y),read(v);addd(b,x,y,v);}dfs(1);for(int i=1;i<=n;i++) col[i].push_back(i);num=n;DSU::init();while(num!=1) getMST::Boruvka();println(cost);debug("%.6lfms\n",1e3*clock()/CLOCKS_PER_SEC);
}
/*
5
2 1 12
3 1 3
4 2 6
5 4 1
2 1 9
3 2 14
4 3 4
5 3 135
2 1 14
3 2 6
4 1 13
5 4 14
2 1 8
3 2 4
4 3 15
5 1 7*/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/880936.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebGPU 版 Kokoro:浏览器端零成本使用高质量 TTS;苹果 ELEGNT 台灯机器人:赋予非人形机器人「情感」

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑…

尝试使用阿里云计算巢部署 DeepSeek-R1

记录一下用阿里云计算巢部署 DeepSeek-R1 的经过。进入阿里云计算巢控制台的服务目录,选择 DeepSeek 社区版,点击「开始部署」,选择最便宜的 ECS 实例 GRID 虚拟化4核30G,费用是 1.748/小时。点击「立即创建」,然后控制台会显示正在部署的状态。部署完成后,控制台会显示公…

未来已来:云手机+AI如何重塑Facebook、Google的智能营销生态

未来已来:云手机+AI如何重塑Facebook、Google的智能营销生态 在数字化浪潮奔涌的当下,科技融合正以令人惊叹的速度重塑各个行业,智能营销领域更是首当其冲。云手机与AI自动化工具的深度融合,为Facebook、Google构建的庞大智能营销生态带来了颠覆性的变革,开拓出全新的发展…

Burp Suite 2024激活汉化

转载自https://blog.csdn.net/m0_52985087/article/details/140299827 前言在项目即将上线阶段,迈入生产环境之际,确保其安全性成为我们不可忽视的首要任务。为筑起一道坚不可摧的安全防线,我们借助业界公认的网络安全利器——Burp Suite,我们将展开一场全面的安全测试,旨…

清华权威出品!104页《DeepSeek从入门到精通》免费领,解锁AI时代的核心竞争力!

引言: 在AI技术席卷全球的今天,如何高效驾驭大模型工具已成为个人与企业脱颖而出的关键。清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室余梦珑博士后团队倾力打造的《DeepSeek从入门到精通》电子书重磅发布!全书104页,从基础操作到高阶技巧,手把手教你玩转国产顶…

win11家庭中文版登录应用提示:“为了对电脑进行保护,已经阻止此应用”

1.家庭中文版组策略里面禁用:以管理员批准模式运行所有管理员 win11打不开组策略,需要复制文本内容到记事本,修改为bat后缀执行 @echo off pushd "%~dp0" dir /b c:\Windows\servicing\Packages\Microsoft-Windows-GroupPolicy-ClientExtensions-Package~3*.mum …

4种比常见的线程池和线程同步买票问题

线程池 所谓的线程池:其实就是线程对象的容器。 可以根据需要,在启动时,创建1个或者多个线程对象。 java中有4种比较常见的线程池。 1.固定数量的线程对象。 2.根据需求动态创建线程:动态创建线程:根据需求来创建线程的个数,会自动给我们分配合适的线程个数来完成任务。 3.…

12. Makefile文件

一、什么是Makefile文件Makefile 文件时一种用于管理和自动化软件编译过程的文本文件。它通常包含了一系列规则,这些规则描述了如何根据源代码文件生成可执行文件或者其它目标文件。Makefile 的核心概念是规则和依赖关系,规则定义了如何生成一个或多个目标文件,而依赖关系则…

busybox 设置登录用户名及密码

1、配置 busybox2、替换新的 /bin/busybox,建立 /bin/login、/sbin/getty 软链接ln -sf /bin/busybox ./bin/login ln -sf /bin/busybox ./sbin/getty3、设置 /etc/inittab 不需要登录:ttyS0::respawn:/bin/ash -l -i需要登录:ttyS0::respawn:/sbin/getty 115200 ttyS04、设…

DoIP 协议详解

转载:车载以太网DoIP 协议,万字长文详解_doip协议-CSDN博客 一、前言 DoIP(Diagnostic Communication over Internet Protocol) 协议是一种用于汽车诊断通信的协议,它允许通过IP网络(如以太网)进行诊断操作。 DoIP协议的设计初衷是为了解决传统基于CAN (Controller Area N…

2025:白手起家,两娃的爸准备创业

前言 2024年陆陆续续听到老东家几个同事被裁的消息,倒有些后悔2023年自己主动提出离职,结束北漂回老家。算了下,损失个小几十万。 2024年6月份来了一场彻彻底底的自我反思,找不到明确目标,于是稀里糊涂定了两个计划:每天读书,围绕技术、文学、创业类。 粉丝数涨到150。工…