#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 100001
int n;
bool vis[N];
struct node{
int v;
node *next;
};
struct headnode{
node *head;
}vertex[N];
struct typenode{
int x,length;
};
int maxn;
int st;
queue<typenode> p;
void bfs(int pos){
while(!p.empty()) p.pop();
memset(vis,0,sizeof(vis));
typenode temp;
temp.length=0;
temp.x=pos;
vis[pos]=1;
p.push(temp);
while(!p.empty()){
typenode a=p.front();
p.pop();
if(a.length>maxn){
maxn=a.length;
st=a.x;
}
node *son=vertex[a.x].head;
while(son!=NULL){
if(!vis[son->v]){
typenode b;
b.x=son->v;
b.length=a.length+1;
vis[son->v]=1;
p.push(b);
}
son=son->next;
}
}
}
int main(){
int t,k;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
int r,c;
for(int i=1;i<=n;i++)
vertex[i].head=NULL;
for(int i=1;i<n;i++){
scanf("%d%d",&r,&c);
node *temp=new node;
temp->v=c;
temp->next=NULL;
temp->next=vertex[r].head;
vertex[r].head=temp;
node *temp2=new node;
temp2->v=r;
temp2->next=NULL;
temp2->next=vertex[c].head;
vertex[c].head=temp2;
}
maxn=0;
bfs(1);
maxn=0;
bfs(st);
int l=maxn;
while(k--){
int m;
scanf("%d",&m);
if(l>=m) printf("%d\n",m-1);
else printf("%d\n",l+(m-l-1)*2);
}
}
return 0;
}
本题的实质是求树的直径,只需要两次bfs确定直径的任意一对起点与终点即可,在长度小于树直径的情况就不说,在长度大于树直径时,因为要求的是最小的费用,所以在
直径这条路上走的时候,我们总是作出最优的选择,我们不会为了到达某一点而走超过2次,也就是说我们不会走多余重复的路,在走的过程中能加进去点就走,这里是指大于树直径的部分。
下图说明这种情况:如果要走过的点的个数是8,则我们肯定是如图中蓝色路线走,不走(8)这个点,也就是说我们肯定要走完直径,因为直径只需走一次,多余直径部分我们总是会作出最优的选择,也就是说多余部分的每一个点的边我们只走两次。
然后就是这题数据比较大,只能用邻接表才能存储边,也可用vector实现,因为曾经受过vector的伤(超时),所以在数据比较大的时候基本就不用vector了。
下面是后来写的加上释放空间的代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 100001
int n;
bool vis[N];
struct node{
int v;
node *next;
};
struct headnode{
node *head;
}vertex[N];
struct typenode{
int x,length;
};
int maxn;
int st;
queue<typenode> p;
void bfs(int pos){
while(!p.empty()) p.pop();
memset(vis,0,sizeof(vis));
typenode temp;
temp.length=0;
temp.x=pos;
vis[pos]=1;
p.push(temp);
while(!p.empty()){
typenode a=p.front();
p.pop();
if(a.length>maxn){
maxn=a.length;
st=a.x;
}
node *son=vertex[a.x].head;
while(son!=NULL){
if(!vis[son->v]){
typenode b;
b.x=son->v;
b.length=a.length+1;
vis[son->v]=1;
p.push(b);
}
son=son->next;
}
}
}
void release(){
for(int i=1;i<=n;i++){
node *p=vertex[i].head;
while(p!=NULL){
vertex[i].head=p->next;
delete p;
p=vertex[i].head;
}
}
}
int main(){
int t,k;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
int r,c;
for(int i=1;i<=n;i++)
vertex[i].head=NULL;
for(int i=1;i<n;i++){
scanf("%d%d",&r,&c);
node *temp=new node;
temp->v=c;
temp->next=NULL;
temp->next=vertex[r].head;
vertex[r].head=temp;
node *temp2=new node;
temp2->v=r;
temp2->next=NULL;
temp2->next=vertex[c].head;
vertex[c].head=temp2;
}
maxn=0;
bfs(1);
maxn=0;
bfs(st);
int l=maxn;
release();
while(k--){
int m;
scanf("%d",&m);
if(l>=m) printf("%d\n",m-1);
else printf("%d\n",l+(m-l-1)*2);
}
}
return 0;
}