首页 > 代码库 > 算法训练 安慰奶牛 最小生成树+构造
算法训练 安慰奶牛 最小生成树+构造
http://lx.lanqiao.cn/problem.page?gpid=T16
题意:n个点,p条边,n,p<=1e5.每个点都有权值c[i],求选择一个点出发遍历所有点后返回需要的最小代价?
容易发现 每条边都经历了两次,边(u,v) 第一次达到v时ans+=c[v],v返回u时ans+=c[u] 则构造边为:安慰两个点(u,v)的代价为 2*w+c[u]+c[v],求出MST即可
#include <bits/stdc++.h> using namespace std; const int inf=1e9; const int N=2e5+20; struct node{ int u,v,w; }e[N]; int n,p,c[N],d[N],vis[N],ans; int fa[N]; bool cmp(node a,node b) { return a.w<b.w; } int find(int x) { if(fa[x]!=x) fa[x]=find(fa[x]); return fa[x]; } void Union(int x,int y) { int fx=find(x),fy=find(y); fa[fx]=fy; } //每次用最小代价把两个连通分量合成一个 void Kruskal() { for(int i=1;i<=n;i++) fa[i]=i; sort(e,e+p,cmp); for(int i=0;i<p;i++) { int u=e[i].u,v=e[i].v,w=e[i].w; if(find(u)!=find(v)) { Union(u,v); ans+=w; } } } int main() { while(cin>>n>>p) { int mn=inf; ans=0; int u,v,w; for(int i=1;i<=n;i++) { cin>>c[i]; mn=min(c[i],mn);//选择slepp的地方,起点 } for(int i=0;i<p;i++) { cin>>u>>v>>w; e[i].u=u,e[i].v=v; e[i].w=2*w+c[u]+c[v];//安慰u,v两个奶牛所需要的时间 } Kruskal(); memset(vis,0,sizeof(vis)); cout<<ans+mn<<endl; } return 0; }
算法训练 安慰奶牛 最小生成树+构造
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。