CF 120F Spider 树的直径 简单题
一个男孩有n只玩具蜘蛛,每只蜘蛛都是一个树的结构,现在男孩准备把这n只小蜘蛛通过粘贴节点接在一起,形成一只大的蜘蛛。大的蜘蛛也依然是树的结构。输出大的蜘蛛的直径。
知识:
树的直径是指树上的最长简单路
求树的直径有个结论:
假设s-t这条路径为树的直径,或者称为树上的最长路。
从任意一点u出发搜到的最远的点一定是s、t中的一点,然后再从这个最远点开始搜,就可以搜到另一个最长路的端点,即用两遍广搜或者深搜就可以找出树的最长路
证明:反证法。
那回到这道题,要使得大蜘蛛的直径最大,就要使连接的小蜘蛛都是用s,t2个点来和其他蜘蛛连接
所以大蜘蛛的直径就是小蜘蛛的直径的和
1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 5 using namespace std; 6 7 const int maxn=105; 8 const int inf=0x3f3f3f3f; 9 10 struct Edge 11 { 12 int to,next; 13 }; 14 Edge edge[maxn<<1]; 15 int head[maxn]; 16 int tot; 17 bool vis[maxn]; 18 struct Point 19 { 20 int num,dis; 21 }; 22 23 void init() 24 { 25 memset(head,-1,sizeof head); 26 tot=0; 27 } 28 29 void addedge(int u,int v) 30 { 31 edge[tot].to=v; 32 edge[tot].next=head[u]; 33 head[u]=tot++; 34 } 35 36 //返回树的直径 37 int solve(int m); 38 //返回结构体,树的节点和节点到u的距离 39 Point bfs(int u,int m); 40 41 int main() 42 { 43 freopen("input.txt","r",stdin); 44 freopen("output.txt","w",stdout); 45 int n; 46 scanf("%d",&n); 47 int ans=0; 48 for(int i=1;i<=n;i++) 49 { 50 init(); 51 int m; 52 scanf("%d",&m); 53 for(int i=1;i<m;i++) 54 { 55 int u,v; 56 scanf("%d %d",&u,&v); 57 addedge(u,v); 58 addedge(v,u); 59 } 60 ans+=solve(m); 61 } 62 printf("%d\n",ans); 63 64 return 0; 65 } 66 67 int solve(int m) 68 { 69 Point cnt=bfs(1,m); 70 Point ret=bfs(cnt.num,m); 71 return ret.dis; 72 } 73 74 Point bfs(int s,int m) 75 { 76 memset(vis,false,sizeof vis); 77 Point start; 78 start.num=s; 79 start.dis=0; 80 vis[s]=true; 81 queue<Point>que; 82 while(!que.empty()) 83 que.pop(); 84 que.push(start); 85 Point ret; 86 while(!que.empty()) 87 { 88 Point u=que.front(); 89 que.pop(); 90 if(que.empty()) 91 { 92 ret.num=u.num; 93 ret.dis=u.dis; 94 } 95 for(int i=head[u.num];~i;i=edge[i].next) 96 { 97 int v=edge[i].to; 98 if(vis[v]) 99 continue; 100 Point uu; 101 uu.num=v; 102 uu.dis=u.dis+1; 103 vis[v]=true; 104 que.push(uu); 105 } 106 } 107 return ret; 108 }