您的位置:首页 > 其它

hdu4607树的直径,spfa

2013-08-20 21:13 363 查看
链接: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\n",k-1);
else printf("%d\n",(k-p-1)*2+p);
}

}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: