先任意取一个人的位置,spfa一遍找最远的另一个人的点,然后再从另一个人的位置开始再进行一边spfa
求得的最远路径即为这n个人在这棵树中的直径ans,ans/2向上取整即为答案
AC代码:
语言:C++ 代码长度:1964 运行时间: 38 ms 占用内存:4192K
1 #include<vector> 2 #include<cstdio> 3 #include<iostream> 4 #include<cmath> 5 #include<queue> 6 #define numm ch-48 7 #define pd putchar(' ') 8 #define pn putchar(' ') 9 #define pb push_back 10 #define fi first 11 #define se second 12 #define fre1 freopen("1.txt","r",stdin) 13 #define fre2 freopen("2.txt","w",stdout) 14 using namespace std; 15 template <typename T> 16 void read(T &res) { 17 bool flag=false;char ch; 18 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true); 19 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm); 20 flag&&(res=-res); 21 } 22 template <typename T> 23 void write(T x) { 24 if(x<0) putchar('-'),x=-x; 25 if(x>9) write(x/10); 26 putchar(x%10+'0'); 27 } 28 const int maxn=100010; 29 const int N=1010; 30 //const int M=10010; 31 const int inf=0x3f3f3f3f; 32 typedef long long ll; 33 struct edge { 34 int to,net,w; 35 }e[maxn<<1]; 36 int dis[maxn],cnt=0,head[maxn]; 37 int pos,ans,n,k; 38 bool vis[maxn]; 39 int a[maxn]; 40 void add(int u,int v,int w) { 41 e[++cnt].to=v; 42 e[cnt].w=w; 43 e[cnt].net=head[u]; 44 head[u]=cnt; 45 } 46 void bfs(int u) { 47 fill(dis+1,dis+1+n,0); 48 fill(vis+1,vis+1+n,false); 49 vis[u]=true; 50 queue<int>que; 51 que.push(u); 52 while(!que.empty()) { 53 int k=que.front(); 54 que.pop(); 55 for(int i=head[k];i;i=e[i].net) { 56 int to=e[i].to; 57 if(!vis[to]) { 58 if(dis[to]<dis[k]+e[i].w) 59 dis[to]=dis[k]+e[i].w; 60 que.push(to); 61 vis[to]=true; 62 } 63 } 64 } 65 ans=0; 66 for(int i=1;i<=k;i++) { 67 if(ans<dis[a[i]]) { 68 ans=dis[a[i]]; 69 pos=i; 70 } 71 } 72 return ; 73 } 74 int main() 75 { 76 read(n),read(k); 77 for(int i=1;i<=n-1;i++) { 78 int u,v,w; 79 read(u),read(v); 80 add(u,v,1); 81 add(v,u,1); 82 } 83 int x; 84 for(int i=1;i<=k;i++) 85 read(a[i]); 86 bfs(a[1]); 87 bfs(a[pos]); 88 ans=(ans%2)?(ans/2+1):ans/2; 89 write(ans);pn; 90 return 0; 91 }