BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树树上dfs性质
Posted Leohh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树树上dfs性质相关的知识,希望对你有一定的参考价值。
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1232
题意:
给你一个无向图,n个点,m条边。
每条边有边权len[i][j],每个点有点权c[i]。
让你找一棵生成树,并在这棵树上找一个根。
从根开始dfs整棵树,每经过一条边(或一个点),花费加上对应的边权(点权)。
问你最小的花费。
题解:
树上dfs性质:
花费 = ∑ (2*len[i][j] + c[i] + c[j]) + c[root]
(1)每一条边要经过两次。
(2)每一条边的两个端点会分别被经过一次。
(3)起点要多经过一次。
所以加边的时候,边权要设为 2*len[i][j] + c[i] + c[j]。
跑一遍kruskal,然后给答案加上最小的一个点权。
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <algorithm> 5 #include <vector> 6 #define MAX_N 10005 7 #define INF 10000000 8 9 using namespace std; 10 11 struct Edge 12 { 13 int sour; 14 int dest; 15 int len; 16 Edge(int _sour,int _dest,int _len) 17 { 18 sour=_sour; 19 dest=_dest; 20 len=_len; 21 } 22 Edge(){} 23 friend bool operator < (const Edge &a,const Edge &b) 24 { 25 return a.len<b.len; 26 } 27 }; 28 29 int n,m; 30 int ans; 31 int c[MAX_N]; 32 int par[MAX_N]; 33 vector<Edge> edge; 34 35 void init_union_find() 36 { 37 for(int i=1;i<=n;i++) 38 { 39 par[i]=i; 40 } 41 } 42 43 int find(int x) 44 { 45 return par[x]==x?x:par[x]=find(par[x]); 46 } 47 48 void unite(int x,int y) 49 { 50 int px=find(x); 51 int py=find(y); 52 if(px==py) return; 53 par[px]=py; 54 } 55 56 bool same(int x,int y) 57 { 58 return find(x)==find(y); 59 } 60 61 int kruskal() 62 { 63 init_union_find(); 64 sort(edge.begin(),edge.end()); 65 int cnt=0; 66 int res=0; 67 for(int i=0;i<edge.size();i++) 68 { 69 Edge temp=edge[i]; 70 if(!same(temp.sour,temp.dest)) 71 { 72 cnt++; 73 res+=temp.len; 74 unite(temp.sour,temp.dest); 75 } 76 } 77 return cnt==n-1?res:-1; 78 } 79 80 void read() 81 { 82 cin>>n>>m; 83 for(int i=1;i<=n;i++) 84 { 85 cin>>c[i]; 86 } 87 int a,b,v; 88 for(int i=0;i<m;i++) 89 { 90 cin>>a>>b>>v; 91 edge.push_back(Edge(a,b,2*v+c[a]+c[b])); 92 } 93 } 94 95 int find_min() 96 { 97 int minn=INF; 98 for(int i=1;i<=n;i++) 99 { 100 minn=min(minn,c[i]); 101 } 102 return minn; 103 } 104 105 void solve() 106 { 107 ans=kruskal(); 108 ans+=find_min(); 109 } 110 111 void print() 112 { 113 cout<<ans<<endl; 114 } 115 116 int main() 117 { 118 read(); 119 solve(); 120 print(); 121 }
以上是关于BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树树上dfs性质的主要内容,如果未能解决你的问题,请参考以下文章
bzoj 1232 [Usaco2008Nov]安慰奶牛cheer
bzoj 1232: [Usaco2008Nov]安慰奶牛cheer最小生成树
BZOJ 1232 [Usaco2008Nov]安慰奶牛cheer:最小生成树树上dfs性质
Bzoj 1229: [USACO2008 Nov]toy 玩具