大臣的旅费
Posted mabeytang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了大臣的旅费相关的知识,希望对你有一定的参考价值。
问题描述
很久以前,T王国空前繁荣。为了更好地管理国家,王国修建了大量的快速路,用于连接首都和王国内的各大城市。
为节省经费,T国的大臣们经过思考,制定了一套优秀的修建方案,使得任何一个大城市都能从首都直接或者通过其他大城市间接到达。同时,如果不重复经过大城市,从首都到达每个大城市的方案都是唯一的。
J是T国重要大臣,他巡查于各大城市之间,体察民情。所以,从一个城市马不停蹄地到另一个城市成了J最常做的事情。他有一个钱袋,用于存放往来城市间的路费。
聪明的J发现,如果不在某个城市停下来修整,在连续行进过程中,他所花的路费与他已走过的距离有关,在走第x千米到第x+1千米这一千米中(x是整数),他花费的路费是x+10这么多。也就是说走1千米花费11,走2千米要花费23。
J大臣想知道:他从某一个城市出发,中间不休息,到达另一个城市,所有可能花费的路费中最多是多少呢?
输入的第一行包含一个整数n,表示包括首都在内的T王国的城市数
城市从1开始依次编号,1号城市为首都。
接下来n-1行,描述T国的高速路(T国的高速路一定是n-1条)
每行三个整数Pi, Qi, Di,表示城市Pi和城市Qi之间有一条高速路,长度为Di千米。
输出一个整数,表示大臣J最多花费的路费是多少。
1 2 2
1 3 1
2 4 5
2 5 4
大臣J从城市4到城市5要花费135的路费。
ALgorithm
一共有 n 个点,共 n - 1 条路线,且任意两点之间有路线,无环,因此这是一个树,也是一个无环无向图。
因此就可以使用DFS或BFS进行搜索,或用Floyd算法求多源点之间的最短路(将边的权改为负)。
但是Floyd算法的时间复杂度很高 O(n^3),只能通过75%的数据,事实上,大约超过 300 个点之后都会运行超时,只是它的测试数据较弱罢了
AC
首先是Floyd算法:
1 /* 2 * 多源点之间的最短距离 3 * 还忽略一个问题, 那就是邻接矩阵的大小 4 */ 5 #include<iostream> 6 #include<cstring> 7 #include<cmath> 8 9 using namespace std; 10 11 const int MAX_V = 1009; 12 const int INF = 1e6; 13 14 int e[MAX_V][MAX_V]; 15 int n = 0; 16 17 void print(int a[MAX_V][MAX_V]) 18 { 19 for(int i=1;i<=n;i++){ 20 for(int j=1;j<=n;j++){ 21 cout<<a[i][j]<<‘ ‘; 22 } 23 cout<<‘ ‘; 24 } 25 } 26 27 int main() 28 { 29 // Init 放在while(cin)里面出问题,,, 30 for(int i=1;i<=MAX_V;i++) 31 for(int j=1;j<=MAX_V;j++){ 32 if(i == j){ 33 e[i][j] = 0; 34 } 35 else{ 36 e[i][j] = INF; 37 } 38 } 39 while(cin>>n) 40 { 41 int a, b, t; 42 int ret = 1; 43 for(int i=1;i<n;i++){ 44 cin>>a>>b>>t; 45 e[a][b] = e[b][a] = -t; // 赋负权 46 } 47 // print(e); 48 // floyd 49 // 居然没有 0 ...... 50 for(int k=1;k<=n;k++) 51 for(int i=1;i<=n;i++) 52 for(int j=1;j<=n;j++) 53 // 非得逼我手算一次才能发现问题所在...(abs) 54 if(abs(e[i][j]) > abs(e[i][k] + e[k][j])){ 55 if(e[i][j] == 0) // 负权要注意一下 ,手算了一次... 56 continue; 57 e[i][j] = e[i][k] + e[k][j]; 58 ret = min(e[i][j], ret); 59 } 60 // print(e); 61 ret = -ret; 62 int ans = (11 + (ret+10))*(ret)/2; 63 cout<<ans<<endl; 64 break; 65 } 66 67 return 0; 68 }
接下来是深搜:
1 /* 2 * 比较典型的图或树的搜索 3 * 这个图比较稀疏, 邻接表可能会好一点 4 * 我们只要搜索度为 1 的点就好, 它一定是起点或者终点 5 * 因为如果度大于 1 的点是终点的话,一定可以继续走下去 6 - 后记 - :我没想到怎样避免不搜索图中遇到它... 7 - 现在有想法了, 如果它是起点,那么 dis = 0 8 * 那么它一定还可以继续前进 9 * ----------------------------------- 10 * 此外, 还可以用Floyd算法来求多源点之间的最短距离 11 * 这里的距离是求最长距离,所以赋予其负的权值就 ok 12 */ 13 #include<iostream> 14 #include<vector> 15 #include<algorithm> 16 #include<cstring> 17 18 using namespace std; 19 20 const int MAX_V = 10009; // 题目没有说最大城市的数量 21 int ret = -1; // 最大花费 22 int dis = 0; // 当前走的距离 23 bool book[MAX_V]; 24 int s = 0; 25 int km = 0; 26 int loc = 0; 27 28 struct edge{ 29 int to; // 去的点 30 int len; // 两点之间的距离 31 }; 32 33 vector<edge> G[MAX_V]; 34 35 // 搜索起点,从 1 开始找最远的距离 36 void finds(int a, int km) 37 { 38 // cout<<a<<endl; 39 if(G[a].size() == 1 && km != 0){ 40 if(km > s){ 41 loc = a; 42 s = km; 43 } 44 } 45 for(int i=0;i<G[a].size();i++){ 46 if(book[G[a].at(i).to] == true){ 47 book[G[a].at(i).to] = false; // 标记当前点 48 finds(G[a].at(i).to, km+G[a].at(i).len); 49 book[G[a].at(i).to] = true; 50 } 51 } 52 } 53 54 // 费用最大,即走的路程最多 55 void dfs(int a, int dis) 56 { 57 if(G[a].size() == 1 && dis != 0){ // 到了度为1的点,搜索结束 58 ret = max(dis, ret); 59 return; 60 } 61 for(int i=0;i<G[a].size();i++){ 62 if(book[G[a].at(i).to] == true){ 63 book[G[a].at(i).to] = false; // 标记当前点 64 dfs(G[a].at(i).to, dis+G[a].at(i).len); 65 book[G[a].at(i).to] = true; 66 } 67 } 68 69 return; 70 } 71 72 int main() 73 { 74 int n; 75 // while(cin>>n) 76 cin>>n; 77 { 78 int go; 79 edge E1, E2; 80 while(--n) 81 { 82 cin>>go>>E1.to>>E1.len; 83 G[go].push_back(E1); 84 E2.to = go; E2.len = E1.len; 85 G[E1.to].push_back(E2); 86 } 87 memset(book, true, sizeof(book)); 88 book[1] = false; 89 finds(1, 0); 90 //cout<<"loc: "<<loc<<endl; 91 //cout<<"s: "<<s<<endl; 92 memset(book, true, sizeof(book)); 93 book[loc] = false; 94 dfs(loc, 0); 95 //cout<<"ret: "<<ret<<endl; 96 cout<<((11 + (ret+10))*(ret)/2)<<endl; 97 } 98 99 return 0; 100 } 101 /* 好像是错误的,通过的数据应该是巧合 102 edge mx; 103 mx.len = 0; 104 int s = 0; 105 for(int i=1;i<=N;i++){ // 会不会一定经过权值最大的度为1的点? 106 if(G[i].size() == 1){ 107 if(G[i][0].len > mx.len){ 108 mx = G[i][0]; 109 s = i; 110 } 111 } 112 } 113 */
深搜分两次,第一次找起点,第二次找最长路径。就像提示里说的那样......
2019-02-18
21:19:25
以上是关于大臣的旅费的主要内容,如果未能解决你的问题,请参考以下文章