链接:http://acm.hdu.edu.cn/showproblem.php?pid=4607
题意:前一阵子做的,题意忘记了,大体就是求树的直径,就是树的最长路的长度。
思路:树的直径有这么一个算法,从树上任意一点出发,找一条最长路,终点为A,再从A点出来,找一条最长路,终点为B,那么树的直径就是AB的长度。求最长路可用dfs或者spfa来写。
#include<iostream> #include<vector> #include<queue> #include<cstring> #include<cstdio> using namespace std; const int maxn=100000+5; const int INF=0x3f3f3f3f;//不能随便写,不然后面的memset出错 int n,m; vector<int> list[maxn]; queue<int> q; int dis[maxn]; int inq[maxn]; void spfa(int p) { int u; memset(dis,0x3f,sizeof(dis)); memset(inq,0,sizeof(inq)); //for(int i=0;i<=n;i++) //{ // dis[i]=INF; // inq[i]=0; //} dis[p]=0;inq[p]++; q.push(p); while(!q.empty()) { u=q.front(); q.pop();inq[u]--;//因为某个点可能重复入队,所以出队的时候也要标记,和bfs不同,bfs只用入队标记,因为只入队一次 for(int i=0;i<list[u].size();i++) if(dis[u]+1<dis[list[u][i]]) { dis[list[u][i]]=dis[u]+1; if(inq[list[u][i]]==0) { q.push(list[u][i]); inq[list[u][i]]++; } } } } int main() { int t,u,v,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) list[i].clear(); for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); list[u].push_back(v); list[v].push_back(u); } int p=1; spfa(p); for(int i=2;i<=n;i++) if(dis[i]>dis[p]) p=i; spfa(p); for(int i=2;i<=n;i++) if(dis[i]>dis[p]) p=i; p=dis[p];// while(m--) { scanf("%d",&k); if(k<=p+1) printf("%d ",k-1); else printf("%d ",(k-p-1)*2+p); } } return 0; }