,1、常见的输入树的情况
(1)输入每个结点的父亲编号
//输入每个点的父亲 #include<iostream> #include<cstdio> #include<vector> using namespace std; #define N 10010 vector<int>vec[N]; int x,n,vis[N]; void dfs(int x){ vis[x]=1; for(int i=0;i<vec[x].size();i++){ if(!vis[vec[x][i]])dfs(vec[x][i]); } } int main() { scanf("%d",&n); for(int i=2;i<=n;i++){ scanf("%d",&x); vec[x].push_back(i);//记录每个点的儿子,x点的儿子是第i个点 } dfs(1); return 0; }
(2)输入n-1条边的信息 不定根
//给出n-1条边的信息 遍历树 #include<iostream> #include<vector> #include<cstdio> #include<bits/stdc++.h> using namespace std; #define N 10010 vector<int>vec[N]; int dad[N],x,y,n; void dfs(int x) { for(int i=0;i<vec[x].size();i++){//遍历和它相连的边 if(dad[x]!=vec[x][i]){ dad[vec[x][i]]=x; dfs(vec[x][i]);//进行深搜; } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d%d",&x,&y);//储存双向边 vec[x].push_back(y); vec[y].push_back(x); } dfs(1); return 0; }
2、求树的直径
树上最长的简单路径为树的直径
在树上任选一点u,以u为根进行一遍dfs,求距离u最远的点s,以s为根进行一遍dfs,找到距离s最远的点t,点s和点t之间的路径为树的直径;
//求树的直径 #include<iostream> #include<cstdio> #include<cstring> #include<bits/stdc++.h> using namespace std; #define N 10010 vector<int>vec[N]; int x,y,n,t,s,dis[N]; void dfs(int x) { for(int i=0;i<vec[x].size();i++){ if(!dis[vec[x][i]]){//没有访问过 dis[vec[x][i]]=dis[x]+1;//dis[vec[x][i]]到x的距离为dis[x]的距离+1 dfs(vec[x][i]); } } } int main() { scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); vec[x].push_back(y); vec[y].push_back(x); } dfs(1);//随便找一个点 for(int i=1;i<=n;i++){ if(dis[i]>dis[t])t=i;//找出和它距离最大的那个点 } memset(dis,0,sizeof(dis));//一定要清0 dfs(t);//再找距离t最大的点 for(int i=1;i<=n;i++){ if(dis[i]>dis[s]) s=i; } printf("%d",dis[s]);//这个点到t点的距离为树的直径 return 0; }
3、找到一个点,其所有的子树中最大的子树结点数最少,这个点就是这个树的重心;树的总点数为偶数时,可能会有两个重心。
先随意确定一个根,之后通过一遍dfs将所有子树的大小求出来。
如果有一个点i满足2*size i >=n,并且它的儿子都满足2*size son i <=n,那么这个点就是这个树的重心;
//求树的重心 #include<iostream> #include<cstdio> #include<bits/stdc++.h> using namespace std; #define N 10010 vector<int>vec[N]; int ans,x,y,n,sizd[N],dad[N]; void dfs(int x) { size[x]=1; for(int i=0;i<vec[x].size();i++) { if(dad[x]!=vec[x][i]) { dad[vec[x][i]]=x; dfs(vec[x][i]); size[x]+=size[vec[x][i]];//它本身的个数加上它儿子结点的个数 } } if(size[x]*2>=n&&!ans)//满足重心的条件 { ans=x; } } int main() { scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d",&x,&y); vec[x].push_back(y);//建边 vec[y].push_back(x); } dfs(1);//搜每个点子树结点的个数 printf("%d",ans); return 0; }