您的位置:首页 > 其它

HDU 4607 树的直径

2017-07-31 09:34 239 查看
题意:每条边的长度是1,求访问k个节点,最少走多远。

分析:贪心,首先走直径len,走完直径len+1个点后,走剩下的点(k-len-1),而走这些点最少一定为(k-len-1)*2。

证明:反证法,要是比(k-len-1)*2还短,那么之前的直径len,就不是直径了。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 100000+5;

struct Edge {
int v,c;
};

vector<Edge> G[maxn];

int len;
int tmp;
void dfs(int x,int fa,int dep) {
if(dep>len) {
tmp = x;
len = dep;
}
for(int i=0;i<G[x].size();i++) {
int v = G[x][i].v;
int c = G[x][i].c;
if(v==fa) continue;
dfs(v,x,dep+c);
}
}

int main()
{
//freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--) {

int n,m;
scanf("%d%d",&n,&m);

for(int i=0;i<=n;i++)
G[i].clear();

for(int i=0;i<n-1;i++) {
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back((Edge){v,1});
G[v].push_back((Edge){u,1});
}

len = -1;
dfs(1,-1,0);
int st = tmp;
len = -1;
dfs(st,-1,0);
while(m--) {
int k;
scanf("%d",&k);
if(k<=len+1)
printf("%d\n",k-1);
else {
printf("%d\n",len+(k-len-1)*2);
}
}

}

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