• HDU 5758 Explorer Bo


    题目:Explorer Bo

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5758

    题意:给一棵树,树边的长度都是1,要求遍历他的所有边至少一次,起始点可以任意选,不能回头(但一条边可以遍历多次),可以传送到任意一点,在完成目的的基础上,传送次数越少越好(第一优先级),走过的路越短越好(第二优先级),输出走过的路的总长度。

    思路:

      这道题的难度不算很大,思路很容易就能想出来,但实现细节有点麻烦,比赛时候没去看有点可惜了(容我吹会B,实际上做这题花了一整个下午,WA到死啊,所以末尾附上一些我错过的测试数据)。

      可以想象,传送次数是第一优先级,所以只有当遍历到叶子结点的时候才会使用传送,令 x = 叶子结点数,所以传送次数为:(x+1)/2,而每一次遍历都是从一个叶子结点到另一个叶子结点。

      

      现在对每一条边进行初步计数,假设他下面有奇数个叶子结点,那么这条边要遍历一次,上图的A边初步计数就是遍历1次,因为他下面三个叶子结点可以自己搭配,剩下一个从A边通往外面和别人搭配。图2中A边初步预计要遍历2次,因为下面四个叶子结点不能全部自己搭配,如果这样,那红点就变成了一个新的叶子结点,可能会增加传送次数。所以只能有一对自己搭配,其他两个都要经过A边。

      上面的初步计数可以通过深入优先搜索进行,如果树的叶子结点数是偶数个,那么答案已经出来了,现在要处理叶子结点奇数的情况。(处理原因就是奇数的情况下,叶子结点可以容许再出现一个,就像图二中红点一样)。

      

      现在看图3,A边原本计数是2,但如果总的叶子结点数是奇数,那么我们可以让红点下面的四个点自己搭配,然后红点作为一个新的叶子结点再和别人配对,这样A边的计数就变成了1,原本B边的计数是1(奇数个叶子结点),现在就变成了2,因为如果红点和蓝点配对,那黑点又变成了一个新的叶子结点(但事实上只容许多出一个),所以B边得经过两次。

      所以,我们就要从根结点开始深搜,每次都尝试对某个子树进行改变,将边1变成2,2变成1,然后每次都取最优(也就是子树的边计数减少最多的)。有了思路,代码实现就比较简单了,也可以参考我下面的AC代码。

    AC代码:

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<vector>
      4 using namespace std;
      5 struct ENode
      6 {
      7   int ad;
      8   int num;
      9 };
     10 vector<ENode> e[100010];
     11 bool u[100010];
     12 int sum=0;
     13 int dfs(int rt,int fa,int fi)
     14 {
     15   u[rt]=1;
     16   int s=0;
     17   for(int i=0;i<e[rt].size();i++)
     18   {
     19     if(u[e[rt][i].ad]==0)
     20     {
     21       e[rt][i].num=dfs(e[rt][i].ad,rt,i);
     22       s+=e[rt][i].num;
     23     }
     24   }
     25   sum+=s;
     26   if(s==0) s=1;
     27   if(s&1) s=1;
     28   else s=2;
     29   return s;
     30 }
     31 int dfs2(int rt)
     32 {
     33   int mm=0;
     34   for(int i=0;i<e[rt].size();i++)
     35   {
     36     if(e[rt][i].num==1)
     37     {
     38       int tmp=dfs2(e[rt][i].ad);
     39       if(tmp-1>mm) mm=tmp-1;
     40     }
     41     else if(e[rt][i].num==2)
     42     {
     43       int tmp=dfs2(e[rt][i].ad);
     44       if(tmp+1>mm) mm=tmp+1;
     45     }
     46   }
     47   return mm;
     48 }
     49 int du[100010];
     50 int qiuCha(int n)
     51 {
     52   int co=0;
     53   for(int i=1;i<=n;i++)
     54   {
     55     if(du[i]==1) co++;
     56   }
     57   if(co%2==0) return 0;
     58   return dfs2(1);
     59 }
     60 int main()
     61 {
     62   int t,n,x,y;
     63   scanf("%d",&t);
     64   while(t--)
     65   {
     66     scanf("%d",&n);
     67     for(int i=1;i<=n;i++) e[i].clear();
     68     memset(du,0,sizeof(du));
     69     for(int i=0;i<n-1;i++)
     70     {
     71       scanf("%d%d",&x,&y);
     72       du[x]++;
     73       du[y]++;
     74       ENode tmp;
     75       tmp.ad=y;
     76       tmp.num=0;
     77       e[x].push_back(tmp);
     78       tmp.ad=x;
     79       e[y].push_back(tmp);
     80     }
     81     memset(u,0,sizeof(u));
     82     ENode tmp;
     83     tmp.ad=1;
     84     sum=0;
     85     dfs(1,0,0);
     86     int cha=qiuCha(n);
     87     printf("%d
    ",sum-cha);
     88   }
     89   return 0;
     90 }
     91 
     92 /*
     93 易错数据:
     94 6666
     95 16
     96 9 2
     97 12 2
     98 1 12
     99 9 7
    100 8 4
    101 4 9
    102 10 11
    103 11 12
    104 16 10
    105 6 8
    106 13 1
    107 10 3
    108 14 11
    109 6 15
    110 5 6
    111 9
    112 1 2
    113 1 3
    114 3 4
    115 3 5
    116 5 6
    117 5 7
    118 7 8
    119 7 9
    120 10
    121 1 2
    122 1 3
    123 1 4
    124 1 6
    125 6 7
    126 7 8
    127 7 9
    128 7 10
    129 7 5
    130 12
    131 1 2
    132 1 3
    133 1 4
    134 1 5
    135 2 7
    136 2 6
    137 6 8
    138 8 9
    139 8 10
    140 7 11
    141 7 12
    142 13
    143 1 2
    144 1 3
    145 3 4
    146 3 5
    147 5 6
    148 5 7
    149 7 8
    150 8 9
    151 9 10
    152 10 11
    153 11 12
    154 11 13
    155 6
    156 1 2
    157 2 3
    158 2 4
    159 2 5
    160 2 6
    161 
    162 答案是:
    163 18
    164 9
    165 9
    166 12
    167 13
    168 5
    169 */
  • 相关阅读:
    mysql复习相关
    OpenStack三种类型的NAT转换
    openstack资料相关
    [转]Web 调试工具之 Advanced REST client
    [转]Aspose.Words.dll 将 Word 转换成 html
    [Android] 开发第十天
    [win10]遇坑指南
    [转]Explorer.exe的命令行参数
    [Android] 开发第九天
    [Android] 开发第八天
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/5712300.html
Copyright © 2020-2023  润新知