HDU 5423 Rikka with Tree(简单DFS+枚举)

来源:互联网 发布:网络信息安全工作总结 编辑:程序博客网 时间:2024/06/12 18:26

http://acm.hdu.edu.cn/showproblem.php?pid=5423

现在感觉到一个很大的障碍就是读题慢而且经常读错题。一道题目一般要读好几遍才明白意思。这一方面还需要多练。这题也是,读了好几遍题意才读懂。言归正传说题解。


题意:
对于一棵树T,令F(T,i)F(T,i)为点1到点ii的最短距离(边长是1).

两棵树A和B是相似的当且仅当他们顶点数相同且对于任意的ii都有F(A,i)=F(B,i)F(A,i)=F(B,i).

两棵树A和B是不同的当且仅当他们定点数不同或者存在一个ii使得以1号点为根的时候ii在两棵树中的父亲不同。

一棵树是特殊的当且仅当不存在一棵和它不同的树和它相似


分析: 一棵树是独特的当且仅当任意处于每一个深度的点数是”1 1 1 1 … 1 1 x”。所以直接DFS一下求出每一个点到根的距离然后判断一下就好了 。开始做的时候只认为每个深度的点数是“1 1 1 1 … 1 1 1 ”才符合情况。后来才悟过来原来最后可以有多个叶子节点,但是从1到叶子节点的过程中有且只能有一个子结点。

容易忽视的地方:大概 就是最后可以有多个叶子节点。


AC未成熟代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 1000+10;bool mat[N][N];int cnt[N];int n;void dfs(int x){    for(int i=1;i<=n;i++)    {        if(mat[x][i] || mat[i][x])        {            cnt[i] = cnt[x]+1;            mat[x][i] = mat[i][x] = false;            dfs(i);        }    }   return;}int main(){    while(~scanf("%d",&n))    {        bool ans = true;        memset(mat,false,sizeof(mat));        for(int i=1;i<n;i++)         {            int x,y;            scanf("%d%d",&x,&y);            mat[y][x]=mat[x][y]=true;//无向边        }        memset(cnt,0,sizeof(cnt));        dfs(1);        //以下步骤都是判断,有点繁琐,反正大概就是这个意思        sort(cnt+1,cnt+1+n);        bool flag = false;        int t;        for(int i=1;i<n;i++)        {            if(cnt[i+1]-cnt[i]==1) continue;            else             {                flag=true;                t=i+1;                break;            }        }        if(flag)         {            for(int i=t;i<n;i++)            {                if(cnt[i+1]==cnt[i]) continue;                else                {                    ans = false;                    break;                }            }        }        puts(ans?"YES":"NO");    }    return 0;}
0 0
原创粉丝点击