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 }
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 }
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 }
革命尚未成功,同志仍需努力