树的直径

  给定一棵树,树中每条边都有一个权值,树中两点之间的距离定义为连接两点的路径上的边权之和。树中最远的两个节点之间的距离被称为树的直径。连接这两点的路径被称为树的最长链。
  练手模板题:http://www.joyoi.cn/problem/tyvj-1520
  树的直径有两种求法,时间复杂度都是O(N).我们假设树以N个点N-1条边的无向图的形式给出,并存储在图中。

    void add(int u,int v,int w){
        Edge[++cnt] = (node){v,w,head[u]};
        head[u] = cnt;
    }
    ……
    cin >> n ;
    for(int i= 1;i< n;i++){
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);add(y,x,w);
    }

方法一:两遍dfs求树的直径
  1.从任意一个节点出发,通过dfs(bfs)对树进行一遍遍历。找出与出发点距离最远的点x.
  2.从x节点出发,再一次通过dfs(bfs)对树进行一遍遍历。找出与出发点距离最远的点y.
  x与y点的路径就是树的一条直径。

void dfs(int u){
    vis[u] = 1;
    if(zjx<d[u]){    //找点x,x里维护最远的点的标号
        x= u; zjx = d[u];
    }   
    for(int i = head[u]; i ; i = Edge[i].nxt){
        int v = Edge[i].v, w = Edge[i].w;       
        if(!vis[v]){
            d[v] = d[u] + w;
            dfs(v);
        } 
    }
……
//主函数里
    dfs(1);
    memset(d,0,sizeof(d));  memset(vis,false,sizeof(vis));
    zjx=0;
    dfs(x);
    cout << zjx;

方法二:树上dp
  设dp[u]表示从节点u出发走向以u为根的子树,能够表达的最远节点的距离。详细阐述以后再图文并茂加吧。

void dpdfs(int u){
    vis[u] = 1;
    for(int i = head[u]; i ; i = Edge[i].nxt){
        int v = Edge[i].v, w = Edge[i].w;       
        if(!vis[v]){
            dpdfs(v);
            ans = max(ans , dp[u]+dp[v]+w);
            dp[u] = max(dp[u],dp[v]+w);
        } 
    }
}

猜你喜欢

转载自blog.csdn.net/xuechen_gemgirl/article/details/80393240
今日推荐