树的直径

杭电OJ4607-Park Visit

题意:对于一棵给定的最小生成树,遍历其中固定的顶点数所需要的最短距离

分析:利用树形DP或者两次BFS求出树的直径即可得解


input:

2

13 4

1 2

2 3

2 4

5 4

4 6

6 8

6 9

7 8

9 10

8 11

11 12

11 13

5

7

9

13

output:

4

6

10

18

//Time      842ms
//Memory    5940k
//Date      2015.03.30

#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
//#include <cstdio>
using namespace std;

const int MAXN=100001;
int n,m,d;
vector<int> Edge[MAXN];
int dis[MAXN];

void Tree_Diam(int r,int f){	//树形DP
    int v;
    vector<int>::iterator it;
    dis[r]=1;
    for(it=Edge[r].begin();it!=Edge[r].end();it++){
        v=*it;
        if(v!=f){       	//排除父节点
            Tree_Diam(v,r);
            d=max(d,dis[r]+dis[v]);
            dis[r]=max(dis[r],dis[v]+1);
        }
    }
}
int main(){
//  freopen("in.txt","r",stdin);//调试
    int t,i,j,k,u,v;
    scanf("%d",&t);
    for(i=0;i<t;i++){
        scanf("%d%d",&n,&m);
        for(j=1;j<=n;j++)
            Edge[j].clear();
        for(j=1;j<n;j++){
            scanf("%d%d",&u,&v);
            Edge[u].push_back(v);
            Edge[v].push_back(u);
        }
        d=0;
        memset(dis,0,sizeof(dis));
        Tree_Diam(1,0);

        for(j=0;j<m;j++){
            scanf("%d",&k);
            if(k<=d)
                printf("%d\n",k-1);
            else
                printf("%d\n",d-1+(k-d)*2);
        }
    }
//  fclose(stdin);
    return 0;
}
//Time      1060ms
//Memory    9096k
//Date      2015.03.30

#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;

class Node{
public:
    int id;
    int level[2];
    Node(int i,int l1=0,int l2=0){
        id=i;level[0]=l1;level[1]=l2;
    }
};
const int MAXN=100001;
int n,m;
vector<Node> Edge[MAXN];
int visit[MAXN];

Node BFS(Node u0,int flag){
    Node u(0),v(0),result(0);
    vector<Node>::iterator it;
    queue<Node> q;

    visit[u0.id]=flag;
    q.push(u0);
    while(!q.empty()){
        u=q.front();q.pop();
        for(it=Edge[u.id].begin();it!=Edge[u.id].end();it++){
            v=*it;
            if(visit[v.id]!=flag){
                visit[v.id]=flag;
                v.level[flag]=u.level[flag]+1;
                result=v;
                q.push(v);
            }
        }
    }
    return result;
}
int Tree_Diam(int r){       //两次BFS
    memset(visit,-1,sizeof(visit));
    Node u(r,0,0);
    Node v1=BFS(u,0);
    Node v2=BFS(v1,1);
    return v2.level[1];
}
int main(){
    int t,i,j,k,u,v,d;
    scanf("%d",&t);
    for(i=0;i<t;i++){
        scanf("%d%d",&n,&m);
        for(j=1;j<=n;j++)
            Edge[j].clear();
        for(j=1;j<n;j++){
            scanf("%d%d",&u,&v);
            Edge[u].push_back(Node(v));
            Edge[v].push_back(Node(u));
        }
        d=Tree_Diam(1);

        for(j=0;j<m;j++){
            scanf("%d",&k);
            k--;
            if(k<=d)
                printf("%d\n",k);
            else
                printf("%d\n",d+(k-d)*2);
        }
    }
    return 0;
}

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值