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\n");
71         else printf("YES\n");
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\n");
101         else printf("YES\n");
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\n");
68     else printf("YES\n");
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\n");
84         else printf("NO\n");
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

 

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

 

posted @ 2015-08-31 19:48  mypride  阅读(189)  评论(0编辑  收藏  举报