1021. Deepest Root (25)
来源:互联网 发布:python 游戏编程 pdf 编辑:程序博客网 时间:2024/06/05 22:52
1021. Deepest Root (25)
A graph which is connected and acyclic can be considered a tree. The height of the tree depends on the selected root. Now you are supposed to find the root that results in a highest tree. Such a root is called the deepest root.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<=10000) which is the number of nodes, and hence the nodes are numbered from 1 to N. Then N-1 lines follow, each describes an edge by given the two adjacent nodes' numbers.
Output Specification:
For each test case, print each of the deepest roots in a line. If such a root is not unique, print them in increasing order of their numbers. In case that the given graph is not a tree, print "Error: K components" where K is the number of connected components in the graph.
Sample Input 1:51 21 31 42 5Sample Output 1:
345Sample Input 2:
51 31 42 53 4Sample Output 2:
Error: 2 components
题目类型:dfs/并查集
这一题搞明白了,图的深度遍历dfs以及递归也就清楚了。
*********************这道题要注意一点要用邻接表存储图,如果用邻接矩阵会超时(稀疏图)********************
(1)我开始用的是并查集来求连通分量的个数,再用dfs求每个节点为根节点的数的深度。并查集采用地递归也没用,但是,提交最后一个案例给我报时间超时。一开始edges[][]和visit[]用的是int类型,提交会报内存不够的错误,所以都换成了bool类型。我的代码:
#include<iostream>#include<cstring>using namespace std;const int maxsize=10001;int node[maxsize];bool edges[maxsize][maxsize];bool visit[maxsize]; int deep[maxsize];int onenodedeep=0;int maxlevel=0;int n;int findroot(int a){if(node[a]!=a)//这里用if判断,而不是while(***很重要***) node[a]=findroot(node[a]);return node[a];}int dfs(int v,int level){visit[v]=true;for(int i=1;i<=n;++i)//***这里每个节点都要遍历N个,复杂度非常高(这才是超时的根本) {if(visit[i]==0 && edges[v][i]==true){onenodedeep=level>onenodedeep?level:onenodedeep;dfs(i,level+1);visit[i]=false;//(***很重要***)}}return onenodedeep;}int main(){//freopen("in.txt","r",stdin);cin>>n;for(int i=1;i<=n;++i)node[i]=i;int components=n;int a,b;for(int i=0;i<n-1;++i){cin>>a>>b;node[i+1]=i+1;edges[a][b]=edges[b][a]=true;int roota=findroot(a);int rootb=findroot(b);if(roota!=rootb){--components;node[roota]=rootb;}}if(components>1)cout<<"Error: "<<components<<" components";else{for(int i=1;i<=n;++i){onenodedeep=0;deep[i]=dfs(i,0);if(deep[i]>maxlevel)maxlevel=deep[i];visit[i]=false;}for(int i=1;i<=n;++i)if(deep[i]==maxlevel)cout<<i<<endl;}return 0;}
(2)于是我在计算连通分量的时候同样采用dfs深度遍历,结果一样是有一个测试案例超时。(还是没有解决dfs内部内各节点都进行访问判断的复杂度降低问题)
我的代码如下:
#include<iostream>#include<cstring>using namespace std;const int maxsize=10001;bool edges[maxsize][maxsize];bool visit[maxsize]; int deep[maxsize];int onenodedeep=0;int maxlevel=0;int n;int dfs(int v,int level){visit[v]=1;for(int i=1;i<=n;++i){if(visit[i]==0 && edges[v][i]==1){onenodedeep=level>onenodedeep?level:onenodedeep;dfs(i,level+1);visit[i]=false;//(重要) }}return onenodedeep;}void dfs_con(int v)//深度遍历求连通分量的个数 {visit[v]=1;for(int i=1;i<=n;++i)//***这里每个节点都要遍历N个,复杂度非常高(这才是超时的根本) {if(visit[i]==0 && edges[v][i]==1)dfs_con(i);}}int main(){//freopen("in.txt","r",stdin);cin>>n;int components=0;int a,b;for(int i=0;i<n-1;++i){scanf("%d %d",&a,&b);edges[a][b]=edges[b][a]=true;}for(int i=1;i<=n;++i){if(visit[i]==0){++components;dfs_con(i);}}if(components>1)cout<<"Error: "<<components<<" components";else{memset(visit,0,sizeof(visit));for(int i=1;i<=n;++i){onenodedeep=0;deep[i]=dfs(i,0);if(deep[i]>maxlevel)maxlevel=deep[i];visit[i]=false;//消除当前节点的访问 }for(int i=1;i<=n;++i)if(deep[i]==maxlevel)cout<<i<<endl;}return 0;}提交结果:
(3)看了一下比人的代码,然后写了改进之后的代码,提交通过。
思路大致如下:设置二维的vector向量,把每个节点所连的边push_back()到相应节点的行里,每次递归只对该行所连节点进行深度递归,剪枝去掉非相连接点的访问判断问题,大大的减少了复杂度。(改进之后可以用二个dfs或者dfs+并查集)
我改进的dfs+dfs代码如下:
#include<iostream>#include<cstring>#include<vector> using namespace std;const int maxsize=10001;bool visit[maxsize]; int deep[maxsize];int onenodedeep=0;int maxlevel=0;int n;vector< vector<int> > edges;int dfs(int v,int level){if(edges[v].size()==0 || visit[v]==1)//结束递归的标志 return 1;//这里的返回值不影响要改变的全局变量onenodedeep的值 visit[v]=1;for(int i=0;i<edges[v].size();++i){if(visit[edges[v][i]]==0){onenodedeep=level>onenodedeep?level:onenodedeep;dfs(edges[v][i],level+1);visit[edges[v][i]]=false;//(重要) }}return onenodedeep;}void dfs_con(int v)//dfs求连通分量的个数 {if(edges[v].size()==0 || visit[v]==1)//一条递归路径结束的标志 return ;visit[v]=1;for(int i=0;i<edges[v].size();++i){if(visit[edges[v][i]]==0)// 不再是判断visit[i]==0(**重要**) dfs_con(edges[v][i]);}}int main(){//freopen("in.txt","r",stdin);cin>>n;edges.resize(n+1);int components=0;int a,b;for(int i=1;i<=n-1;++i){scanf("%d %d",&a,&b);edges[a].push_back(b);edges[b].push_back(a);}for(int i=1;i<=n;++i){if(visit[i]==0){++components;dfs_con(i);}}if(components>1)cout<<"Error: "<<components<<" components";else{memset(visit,0,sizeof(visit));for(int i=1;i<=n;++i){onenodedeep=0;deep[i]=dfs(i,0);if(deep[i]>maxlevel)maxlevel=deep[i];visit[i]=false;}for(int i=1;i<=n;++i)if(deep[i]==maxlevel)cout<<i<<endl;}return 0;}提交结果:
(4)别人的代码,提交之后的复杂度是真的低
#include <cstdio>#include <vector>#include <set>#include <algorithm>using namespace std;int n, maxheight = 0;vector<vector<int>> v;bool visit[10010];set<int> s;vector<int> temp;void dfs(int node, int height) { if(height > maxheight) { temp.clear(); temp.push_back(node); maxheight = height; } else if(height == maxheight){ temp.push_back(node); } visit[node] = true; for(int i = 0; i < v[node].size(); i++) { if(visit[v[node][i]] == false) dfs(v[node][i], height + 1); }}int main() { scanf("%d", &n); v.resize(n + 1); int a, b, cnt = 0; for(int i = 0; i < n - 1; i++) { scanf("%d%d", &a, &b); v[a].push_back(b); v[b].push_back(a); } int s1 = 0; for(int i = 1; i <= n; i++) { if(visit[i] == false) { dfs(i, 1); if(i == 1) { for(int j = 0; j < temp.size(); j++) { s.insert(temp[j]); if(j == 0) s1 = temp[j]; } } cnt++; } } if(cnt >= 2) { printf("Error: %d components", cnt); } else { temp.clear(); maxheight = 0; fill(visit, visit + 10010, false); dfs(s1, 1); for(int i = 0; i < temp.size(); i++) s.insert(temp[i]); for(set<int>::iterator it = s.begin(); it != s.end(); it++) printf("%d\n", *it); } return 0;}
(5)
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn=10001; bool vis[maxn]; int a[maxn]; int n; int cnt=0; vector<int> ma[maxn];//邻接表 int d[maxn];//计算以这个点为树根时的最大深度 int dfs(int s)//dfs表示以S为起点所能达到的最大深度 { int ans=0; if(vis[s])return 0;//这个点已经被访问过,明显以这个点的最大深度是0 vis[s]=true; int m=ma[s].size(); for(int i=0; i<m; i++) { if(!vis[ma[s][i]]) { int tmp=dfs(ma[s][i]);//以当前点为起点访问能到达的最大的深度,也就是找出S的邻接点里的,深度,能达到的最大的 ans=max(ans,tmp);//ans记录下最大的深度即可 } } return ans+1;//能到这里说明以S点能到达的深度可以加一,也就是S相邻的顶点里的深度,最大值,加上S点,所以就是ans+1 } void init(int n)//这是并查集的初始化 { for(int i=0; i<=n; i++) a[i]=i; } int find(int x)//并查集查找X的父亲,带路径压缩 { if(a[x]!=x) a[x]=find(a[x]); return a[x]; } void unio(int x,int y)//合并X,Y到一起 { x=find(x); y=find(y); if(a[x]==a[y])return ; a[x]=y; } int main() { int i,j,k,t; // freopen("in.txt","r",stdin); cin>>n; init(n); for(i=1; i<n; i++) { int s,e; cin>>s>>e; unio(s,e); ma[s].push_back(e); ma[e].push_back(s); } int sum=0;//判断连通分量的个数 for(i=1; i<=n; i++) { if(a[i]==i)sum++; } if(sum>1) { printf("Error: %d components\n",sum); return 0; } else for(i=1; i<=n; i++) { memset(vis,0,sizeof(vis)); d[i]=dfs(i); } int maxv=-1;int index=0; for(i=1;i<=n;i++)if(d[i]>maxv){maxv=d[i];index=i;} for(j=1;j<=n;j++)if(d[j]==d[index]) printf("%d\n",j); }(6)
#include<iostream> #include<string.h> #include<vector> using namespace std; #define N 10001 vector<int> edge[N]; int deepest[N]; int visited[N]; int n; int dfs(int now_node){ if(visited[now_node]==1) return 0; visited[now_node]=1; if(edge[now_node].size()==0) return 1; int i,maxdeep=0,tmp; for(i=0;i<edge[now_node].size();i++){//find a deepest from this node if(visited[edge[now_node][i]]==0){ tmp=dfs(edge[now_node][i]); maxdeep=maxdeep>tmp?maxdeep:tmp; } } return maxdeep+1; } int main() { int i,j; cin>>n; for(i=1;i<=n-1;i++){ int v1,v2; cin>>v1>>v2; edge[v1].push_back(v2); edge[v2].push_back(v1); } memset(deepest,0,sizeof(deepest)); int max_deep=0; int flag=0; for(i=1;i<=n;i++){ if(0==flag) memset(visited,0,sizeof(visited)); deepest[i]=dfs(i); max_deep=max_deep>deepest[i]?max_deep:deepest[i]; for(j=i;j<=n;j++){//check if it is a connected graph if(visited[j]==0){ flag++; i=j-1; break; } } } if(flag>0){ cout<<"Error: "<<flag+1<<" components"<<endl; } else{ for(i=1;i<=n;i++){ if(deepest[i]==max_deep) cout<<i<<endl; } } return 0; }
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 1021. Deepest Root (25)
- 部件和布局
- TabLayout的简单使用
- 最长回文(Manacher算法)
- iOS- 报错(崩)[< > setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key
- Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'
- 1021. Deepest Root (25)
- HDU 6168
- 安卓开发四大组件
- Kconfig文件
- 华为笔试题——循环节求和
- 使用yaf创建项目
- SSD框架训练自己的数据集
- Google面试题:M-Fraction to Recurring Decimal
- esp_iot_sdk固件函数解释