CEOI 2004 Trial session Problem. Journey DFS
Posted OptimusPrime_L
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CEOI 2004 Trial session Problem. Journey DFS相关的知识,希望对你有一定的参考价值。
PROBLEM
http://www.oi.edu.pl/old/ceoi2004/problems/jou.pdf
分析
这题属于需要一些思考的题目。对于这道题目,我们要了解到这个图其实就是一棵树。如何想到这是树?题目中又这样几句话:
There are n cities in Byteland.
There are only n-1 roads, but connect the cities in such a way that is possible to travel from each city to any other city.
很容易发现这是典型的树的特征。当然,如果还不能看出来,随手画几个图就会发现,要满足这两个条件,这个图一定是一棵树。那么这道题的算法就是树的遍历,根据题目特征,很容易想到,利用DFS解决这道题目。
那么问题来了,如何计算最短路径呢?这个时候可能很难想到,那么可以简单地画几棵树。
经过不断尝试和总结(写一些数据),会发现:MinLength = EdgeLengthSum*2 - MaxEdgeLength(其中MaxEdgeLength是从出发点到某一需要拜访的点的最长距离)
其实仔细一想就明白了。这是一棵树,所以走到某一个点,再去下一个不在同一树枝上的点就要回头走到最小公共父亲。这意味着所有路都会走两边。因为题目中没有说要回到出发点,所以把距离出发点最远的点放在最后走,这样就不需要把这条最长边走两次了。于是就得出了上面这个公式。
程序
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int MAX = 50000 + 1; 4 int EdgeCount, Head[MAX], dist[MAX], n, k, m; 5 long long sum; 6 bool visit[MAX]; 7 struct node 8 { 9 int Next, Aim, Weight; 10 }Edge[MAX]; 11 void insert(int u, int v, int w) 12 { 13 Edge[++EdgeCount] = (node){Head[u],v,w}; 14 Head[u] = EdgeCount; 15 } 16 void DFS(int u, int Father) 17 { 18 for (int i = Head[u]; i>0 ; i = Edge[i].Next) 19 { 20 int v = Edge[i].Aim; 21 if (Father == v) 22 continue; 23 dist[v] = dist[u]+Edge[i].Weight; 24 DFS(v,u); 25 if (visit[v]) 26 sum += 2*Edge[i].Weight; 27 } 28 } 29 int main() 30 { 31 freopen("journey.in","r",stdin); 32 freopen("journey.out","w",stdout); 33 int Max_Edge = 0; 34 cin >> n >> k; 35 int u,v,w; 36 for (int i = 1; i <= n-1; i++) 37 { 38 cin >> u >> v >> w; 39 insert(u,v,w); 40 insert(v,u,w); 41 } 42 cin >> m; 43 for (int i = 1; i <= m; i++) 44 { 45 int c; 46 cin >> c; 47 visit[c] = true; 48 } 49 DFS(k,-1); 50 for (int i = 1; i <= n; i++) 51 { 52 if (visit[i]) 53 Max_Edge = max(Max_Edge, dist[i]); 54 } 55 cout << sum-Max_Edge << endl; 56 return 0; 57 }
以上是关于CEOI 2004 Trial session Problem. Journey DFS的主要内容,如果未能解决你的问题,请参考以下文章