标签:
练了好久的了
过了4题
现在才补
真是懒成dog了---
A
签到
B
练的时候虽然讨论出了正确的做法,,可是当时根本不觉得是对的- -
做法是,求三次树的直径
第一次,求出整棵树的直径,找到直径的中点,将整棵树分成两颗子树
第二次,求出第一棵子树的直径的中点
第三次,求出第二棵子树的直径的中点
-------写了好几天----最后还是看了题解的写法---
自己写的又wa又T的-----好----搓----啊----
有两个地方自己写的时候没有搞太清楚,
先是将整棵子树分成两半的时候,不知道从哪里断开
然后就是找中点的时候,不知道找直径是奇数,偶数的时候该怎么处理,,,
总之,,,就是,,,-----sad------
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<vector> #include<queue> using namespace std; //wei ziji +u >_< const int INF = (1<<30)-1; const int maxn = 5e5+5; int n; int d[maxn],vis[maxn],p[maxn],p1[maxn],p2[maxn]; vector<int>g[maxn]; int st,ed;//ed 记录下找到的直径的 端点 int rr;//直径 void bfs(int s){ queue<int> q; p[s] = 0;d[s] = 1; rr = 1; ed = s; q.push(s); while(!q.empty()){ int u = q.front();q.pop(); for(int i = 0;i < g[u].size();i++){ int v = g[u][i]; if(vis[v]) continue; if(v == p[u]) continue; d[v] = d[u]+1; p[v] = u; q.push(v); if(d[v] > rr){ rr = d[v]; ed = v; } } } } void solve(){ //整棵树的直径 memset(vis,0,sizeof(vis)); bfs(1); bfs(ed); // for(int i = 1;i <= n;i++) printf("p[%d] = %d\n",i,p[i]); // printf("rr = %d ed = %d\n",rr,ed); // for(int i = 1;i <= n;i++) printf("d[%d] = %d\n",i,d[i]); //找将这棵树断开的点,也就是这棵树直径的中点 int mid = ed; int x = d[ed]; while(x != rr/2 +1){ mid =p[mid]; x = d[mid]; // printf("---x = %d\n",x); } // printf("mid = %d\n",mid); int res = 0,c1,c2; // 第一颗子树的 vis[mid] = 1; bfs(p[mid]); st = ed; bfs(ed); c1 = ed;x = d[ed]; while(x != rr/2+1){ c1 = p[c1]; x = d[c1]; } res = max(res,rr/2); //第二棵子树的 vis[mid] = 0; vis[p[mid]] = 1; bfs(mid); st = ed; bfs(ed); c2 = ed;x = d[ed]; while(x!=rr/2+1){ c2 = p[c2]; x = d[c2]; } res = max(res,rr/2); printf("%d %d %d\n",res,c1,c2); } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d",&n); for(int i = 1;i <= n;i++) g[i].clear(); for(int i=1;i < n;i++){ int u,v; scanf("%d %d",&u,&v); g[u].push_back(v); g[v].push_back(u); } solve(); } return 0; }
C
D
dp,,他们做的
E
F
G
H
I
套公式,注意0的时候
J
K
贪心
标签:
原文地址:http://www.cnblogs.com/wuyuewoniu/p/4924650.html