标签:子节点 ems ima equal code ssi continue == inpu
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 14251 | Accepted: 6027 |
Description
Input
Output
Sample Input
1 7 2 6 1 2 1 4 4 5 3 7 3 1
Sample Output
1 2
Source
题目很好理解,就是去掉树上的一个节点,看看剩下的子树中最大的是多少,然后在这些最大值中求一个最小值,如果有多个点都是最小值,那么找一个序号最小的节点。输出节点号,和最小值。
经过简单分析,DFS深度优先搜索可以解决,只需要求出每个节点下子树的总结点个数即可。
这题其实是求重心的裸题!
举例说明:
设有一棵树20个节点,其中有一个节点为u,u有两个孩子节点,设u以下有10个节点,两个孩子分别有6和4个节点,那么对于u来说,最大是多少,应该是20 - 10,6,4中的最大的也就是10.这样等把所有节点的最大值求出后,再求1-n中的最小值,输出该点以及最小值即可。
算法就是DFS,计算出每个节点下的总数,然后保留本节点下的孩子节点子树中的最大值,然后和自己的祖先节点比较求出最大值,最后枚举最小值。
这题一定要建一个双向图,因为树是无向的。
下面是AC代码:
1 #include <stdio.h> 2 #include <string.h> 3 #define max(a,b) (a)>(b)?(a):(b) 4 const int maxn=20010; 5 struct Edge//前向星存边 6 { 7 int to,next; 8 }edge[maxn<<1];//保存双向图 9 int head[maxn],tot; 10 inline void init()//初始化操作 11 { 12 memset(head,-1,sizeof(head)); 13 tot=0; 14 } 15 inline void addedge(int u,int v)//加边 16 { 17 edge[tot].to=v; 18 edge[tot].next=head[u]; 19 head[u]=tot++; 20 } 21 int dp[maxn];//每个节点去掉后其他子树的点数 22 int num[maxn];//每个节点下的节点总数 23 int n; 24 inline void DFS(int u,int pre) 25 { 26 dp[u]=0;//初始化 27 num[u]=1;//初始化 28 for(int i=head[u];i!=-1;i=edge[i].next) 29 { 30 int v=edge[i].to; 31 if(v==pre) 32 continue; 33 DFS(v,u); 34 dp[u]=max(dp[u],num[v]);//求根节点下儿子节点中的最大值 35 num[u]+=num[v];//求根节点下的所有节点数 36 } 37 dp[u]=max(dp[u],n-num[u]);//祖先节点总数的最大值和根节点下儿子节点中的最大值作为本节点的最大值 38 } 39 int main() 40 { 41 int T; 42 scanf("%d",&T); 43 int u,v; 44 while(T--) 45 { 46 scanf("%d",&n); 47 init(); 48 for(int i=1;i<n;i++)//建图 49 { 50 scanf("%d%d",&u,&v); 51 addedge(u,v); 52 addedge(v,u); 53 } 54 DFS(1,-1); 55 int ans1=1,ans2=dp[1]; 56 for(int i=2;i<=n;i++)//求最小值 57 { 58 if(ans2>dp[i]) 59 { 60 ans1=i; 61 ans2=dp[i]; 62 } 63 } 64 printf("%d %d\n",ans1,ans2); 65 } 66 return 0; 67 }
标签:子节点 ems ima equal code ssi continue == inpu
原文地址:http://www.cnblogs.com/ECJTUACM-873284962/p/7279062.html