BZOJ 1232 USACO 2008 Nov. 安慰奶牛Cheer
【题解】
对于每一条边,我们通过它需要花费的代价是边权的两倍加上这条边两个端点的点权。
我们把每条边的边权设为上述的值,然后跑一边最小生成树,再把答案加上最小的点权就好了。
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 const int maxn=200010; 5 long long ans=0; 6 int n,m,fa[maxn],c[maxn],tot; 7 struct edge{int x,y,w;}e[maxn]; 8 void read(int &k){ 9 k=0; int f=1; char c=getchar(); 10 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 11 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 12 k*=f; 13 } 14 bool cmp(edge a,edge b){return a.w<b.w;} 15 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} 16 int main(){ 17 read(n); read(m); ans=0x7f7f7f7f; 18 for (int i=1;i<=n;i++){ 19 read(c[i]); 20 if (c[i]<ans) ans=c[i]; 21 fa[i]=i; 22 } 23 for (int i=1;i<=m;i++){ 24 read(e[i].x); read(e[i].y); read(e[i].w); 25 e[i].w=(e[i].w<<1)+c[e[i].x]+c[e[i].y]; 26 } 27 sort(e+1,e+1+m,cmp); 28 for (int i=1,x,y;i<=m;i++){ 29 if (find(x=e[i].x)!=find(y=e[i].y)) ans+=e[i].w,tot++,fa[find(x)]=find(y); 30 if (tot==n-1) break; 31 } 32 return printf("%d\n",ans),0; 33 }