• 大臣的旅费


    问题描述

    很久以前,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
    5
    1 2 2
    1 3 1
    2 4 5
    2 5 4
    样例输出1
    135
    输出格式

    大臣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 }
    View Code

     接下来是深搜:

      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 */
    View Code

     深搜分两次,第一次找起点,第二次找最长路径。就像提示里说的那样......

    2019-02-18

    21:19:25

  • 相关阅读:
    python 单下划线/双下划线使用总结
    error connection reset by peer 104
    变形课
    求并联电阻值
    HDU2054:A == B ?
    Do the Untwist
    开门人和关门人
    关于HEXO安装失败的解决方法
    代码高亮显示——google-code-prettify
    网站图标——favicon
  • 原文地址:https://www.cnblogs.com/mabeyTang/p/10396112.html
Copyright © 2020-2023  润新知