zoukankan      html  css  js  c++  java
  • hdu 5423 Rikka with Tree(dfs)bestcoder #53 div2 1002

    题意:

    输入一棵树,判断这棵树在以节点1为根节点时,是否是一棵特殊的树。

    相关定义:

    1.  定义f[A, i]为树A上节点i到节点1的距离,父节点与子节点之间的距离为1。

    2.  对于树A与树B,如果A与B的节点数相同,且无论i为何值,f[A, i]与f[B, i]都相等,则A与B为两棵相似的树。

    3.  对于一棵树A,在以节点1为根节点的情况下,如果不存在与其它树与A相似,则A是一棵特殊的树。


    输入:

    包含多组输入样例。

    每组输入样例中首先输入一个整数n,表示一棵含有n个节点的树。

    接下来n-1行,每行两个整数a, b表示a与b相连。

    输出:

    如果这棵树是特殊的树,输出YES,否则输出NO。每组样例占1行。

    题解:

    如果某个节点x的父节点fx到根节点fg的距离dis[fx]与另一个节点fy的dis[fy]相等,且fx != fy, 那么x在fy上的树与x在fx上的树是相似的。

      首先,我们可以证明,如果树A是一条以节点1为根的单链,那么这棵树是特殊的。

      其次,我们可以证明,如果树A以节点1为根时,除了叶节点的父节点出度为x(x>1)外,其它非子节点的出度都为1。那么这棵树也是特殊的。(当然上一个证明包含在这个证明中)。

      除此之外的所有情况,都是非特殊的。

    因此,我们可以先计算出所有节点到根节点(节点1)的距离,然后分析得x2,x3,…xi,…,xn,xi即,到节点1的距离为i的点的数量。根据上面的结论,如果x2到xi的值为1,xi+1的值为m(1<=m<=n-1)则,这棵树是特殊的,否则不是。

    计算树上任一点到节点1的距离,可以用dfs很方便得计算出来,但是在比赛的时候,我脑子抽了,居然用了最短路算法……当然,用最短路确实也能解。

    其次,在统计结果的时候,我用的方法是将dis[],即节点到根节点的距离按从小到大排序,然后从前往后数,当dis[i] == dis[i+1] && dis[i+1] < dis[i+2]时,则不是特殊树。

    看了别人的方法,是统计每种距离的数量的。

    但是,我想说的一点是,我在用sort排序时,写的sort(dis+1, dis+n+1, cmp),其中的cmp(int x, int y)中由于直接写了个return x <= y; 所以爆re爆得欲仙欲死,显示非法访问内存了。然后将<=改成<,就过了……

    用最短路算法时,3次Dijkstra,tle 1次,900+ms 2次。2次Spfa,都是700ms+。

    用dfs,2次是排序的方法,分别是46ms,62ms,1次统计各距离,15ms……看来还是别人家的方法好T_T。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 using namespace std;
     5 const int NN = 2010;
     6 const int N = 10000010;
     7 
     8 int mp[NN][NN];
     9 int dis[NN];
    10 bool vis[NN];
    11 int n;
    12 
    13 bool cmp(int x, int y)
    14 {
    15     return x <= y;            //就死在这个<=上了 = =
    16 }
    17 
    18 void dij()
    19 {
    20     memset(vis, 0, sizeof(vis));
    21     dis[1] = 0;
    22     for(int i = 2; i <= n; i++) dis[i] = mp[1][i];
    23     vis[1] = 1;
    24     for(int i = 1; i < n; i++)
    25     {
    26         int minn = N, k;
    27         for(int j = 1; j <= n; j++)
    28         {
    29             if(!vis[j] && minn > dis[j])
    30             {
    31                 minn = dis[j];
    32                 k = j;
    33             }
    34         }
    35         if(minn == N) break;
    36 
    37         vis[k] = 1;
    38         for(int j = 1; j <= n; j++)
    39         {
    40             if(!vis[j] && dis[j] > dis[k]+mp[j][k]) dis[j] = dis[k]+mp[j][k];
    41         }
    42     }
    43 }
    44 
    45 int main()
    46 {
    47     //freopen("test.in", "r", stdin);
    48     while(~scanf("%d", &n))
    49     {
    50         for(int i = 1; i <= n; i++)
    51         {
    52             for(int j = 1; j < i; j++) mp[i][j] = mp[j][i] = N;
    53             mp[i][i] = 0;
    54         }
    55 
    56         for(int i = 1; i < n; i++)
    57         {
    58             int a, b;
    59             scanf("%d%d", &a, &b);
    60             mp[a][b] = mp[b][a] = 1;
    61         }
    62         dij();
    63         sort(dis+1, dis+n+1, cmp);
    64         bool flag = 0;
    65 
    66         for(int i = 2; i <= n-2; i++)
    67         {
    68             if(dis[i] == dis[i+1] && dis[i+1] < dis[i+2]) {flag = 1; break;}
    69         }
    70         if(flag) printf("NO
    ");
    71         else printf("YES
    ");
    72     }
    73     return 0;
    74 }            
    RE code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <algorithm>
      5 using namespace std;
      6 const int NN = 1010;
      7 const int N = 100010;
      8 
      9 int mp[NN][NN];
     10 int dis[NN];
     11 bool vis[NN];
     12 int n;
     13 
     14 bool cmp(int x, int y)
     15 {
     16     return x < y;                        //...............
     17 }
     18 
     19 void dij()
     20 {
     21     dis[1] = 0;
     22     for(int i = 2; i <= n; i++) dis[i] = mp[1][i];
     23     vis[1] = 1;
     24     for(int i = 1; i < n; i++)
     25     {
     26         int minn = N, k;
     27         for(int j = 1; j <= n; j++)
     28         {
     29             if(!vis[j] && minn > dis[j])
     30             {
     31                 minn = dis[j];
     32                 k = j;
     33             }
     34         }
     35         if(minn == N) break;
     36         vis[k] = 1;
     37         for(int j = 1; j <= n; j++)
     38         {
     39             if(!vis[j] && dis[j] > dis[k]+mp[j][k]) dis[j] = dis[k]+mp[j][k];
     40         }
     41     }
     42 }
     43 
     44 void Spfa()
     45 {
     46     dis[1] = 0;
     47     for(int i = 2; i <= n; i++) dis[i] = N;
     48     vis[1] = 1;
     49     queue<int>que;
     50     que.push(1);
     51 
     52     int p;
     53     while(!que.empty())
     54     {
     55         p = que.front();
     56         que.pop();
     57         vis[p] = 0;
     58         for(int i = 1; i <= n; i++)
     59         {
     60             if(dis[i] > dis[p]+mp[i][p])
     61             {
     62                 dis[i] = dis[p]+mp[i][p];
     63                 if(vis[i] == 0)
     64                 {
     65                     que.push(i);
     66                     vis[i] = 1;
     67                 }
     68             }
     69         }
     70     }
     71 }
     72 
     73 int main()
     74 {
     75     //freopen("test.in", "r", stdin);
     76     while(~scanf("%d", &n))
     77     {
     78         for(int i = 1; i <= n; i++)
     79         {
     80             for(int j = 1; j < i; j++) mp[i][j] = mp[j][i] = N;
     81             mp[i][i] = 0;
     82             vis[i] = 0;
     83         }
     84 
     85         for(int i = 1; i < n; i++)
     86         {
     87             int a, b;
     88             scanf("%d%d", &a, &b);
     89             mp[a][b] = mp[b][a] = 1;
     90         }
     91         //Spfa();
     92         dij();
     93         sort(dis, dis+n+1, cmp);
     94         bool flag = 0;
     95 
     96         for(int i = 2; i <= n-2; i++)
     97         {
     98             if(dis[i] == dis[i+1] && dis[i+1] < dis[i+2]) {flag = 1; break;}
     99         }
    100         if(flag) printf("NO
    ");
    101         else printf("YES
    ");
    102     }
    103     return 0;
    104 }
    AC dij+spfa
     1 #include <cstdio>
     2 #include <cmath>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int N = 1010;
     8 
     9 struct Edge
    10 {
    11     int to, next;
    12 }edge[N];
    13 
    14 int dis[N], head[N];
    15 bool vis[N];
    16 int n;
    17 
    18 bool cmp(int x, int y)
    19 {
    20     return x < y;
    21 }
    22 
    23 void add(int a, int b, int k)
    24 {
    25     edge[k].to = b;
    26     edge[k].next = head[a];
    27     head[a] = k;
    28 }
    29 
    30 void init()
    31 {
    32     memset(edge, -1, sizeof(edge));
    33     memset(head, -1, sizeof(head));
    34     memset(dis, -1, sizeof(dis));
    35     for(int i = 1; i < n; i++)
    36     {
    37         int a, b;
    38         scanf("%d%d", &a, &b);
    39         add(a, b, i);
    40     }
    41 }
    42 
    43 void dfs(int x, int k)
    44 {
    45     for(int i = head[x]; i != -1; i = edge[i].next)
    46     {
    47         int v = edge[i].to;
    48         if(!vis[v])
    49         {
    50             vis[v] = 1;
    51             dis[v] = k;
    52             dfs(v, k+1);
    53             vis[v] = 0;
    54         }
    55     }
    56 }
    57 
    58 void outit()
    59 {
    60 /*
    61     sort(dis, dis+n+1, cmp);
    62     bool flag = 0;
    63     for(int i = 2; i <= n-2; i++)
    64     {
    65         if(dis[i] == dis[i+1] && dis[i+1] < dis[i+2]) {flag = 1; break;}
    66     }
    67     if(flag) printf("NO
    ");
    68     else printf("YES
    ");
    69 */
    70         int sum[N];
    71         memset(sum, 0, sizeof(sum));
    72         for(int i = 1; i <= n; i++) sum[dis[i]]++;
    73         int ans = 0;
    74         for(int i = 1; i <= n; i++)
    75         {
    76             if(sum[i] == 1) ans++;
    77             else
    78             {
    79                 if(sum[i+1] == 0) ans = n;
    80                 break;
    81             }
    82         }
    83         if(ans == n) printf("YES
    ");
    84         else printf("NO
    ");
    85 }
    86 
    87 int main()
    88 {
    89     //freopen("test.in", "r", stdin);
    90     while(~scanf("%d", &n))
    91     {
    92         init();
    93         dfs(1, 1);
    94         outit();
    95     }
    96     return 0;
    97 }
    AC dfs

    革命尚未成功,同志仍需努力

     

  • 相关阅读:
    SpringMVC之@RequestParam @RequestBody @RequestHeader 等详解
    RabbitMQ基础介绍
    linux查看tomcat日志
    HTML-01
    Ajax和json
    使用VBScript实现设置系统环境变量的小程序
    WinForm中重绘TabControl选项卡标题
    Action向视图传值的6种方式
    C#中常用的系统内置委托
    C#中的扩展方法
  • 原文地址:https://www.cnblogs.com/mypride/p/4773936.html
Copyright © 2011-2022 走看看