算法训练 安慰奶牛 最小生成树+构造
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法训练 安慰奶牛 最小生成树+构造相关的知识,希望对你有一定的参考价值。
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; }
以上是关于算法训练 安慰奶牛 最小生成树+构造的主要内容,如果未能解决你的问题,请参考以下文章
BZOJ1232[Usaco2008Nov]安慰奶牛cheer 最小生成树
bzoj 1232: [Usaco2008Nov]安慰奶牛cheer最小生成树