博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
无向图的直径以及树的直径
阅读量:4154 次
发布时间:2019-05-25

本文共 2715 字,大约阅读时间需要 9 分钟。

转载:

在一張無向圖上面,給定圖上一點,以最短路徑長度當作距離,找出離此點最遠的一點,這兩點之間的距離就叫做「偏心距」。

要計算一張無向圖的直徑與半徑是很簡單的,首先算好所有兩點之間最短路徑,然後按照定義來算就可以了。

先用floyd算法,再找最长的即可

  1. int d[10][10];  // adjacency matrix
  2. int ecc[10];    // 各點的偏心距
  3.  
  4. void diameter_radius()
  5. {
  6.     // Floyd-Warshall Algorithm
  7.     for (int k=0k<10; ++k)
  8.         for (int i=0i<10; ++i)
  9.             for (int j=0j<10; ++j)
  10.                 d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
  11.  
  12.     // 計算偏心距
  13.     memset(ecc0x7fsizeof(ecc));
  14.     for (int i=0i<10; ++i)
  15.         for (int j=0j<10; ++j)
  16.             ecc[i] = min(ecc[i], d[i][j]);
  17.  
  18.     // 計算直徑和半徑
  19.     int diameter = 0;
  20.     int radius = 1e9;
  21.     for (int i=0i<10; ++i)
  22.     {
  23.         diameter = max(diameterecc[i]);
  24.         radius   = min(radius  , ecc[i]);
  25.     }
  26.  
  27. /*
  28.     // 直徑也可以這樣算
  29.     for (int i=0; i<10; ++i)
  30.         for (int j=0; j<10; ++j)
  31.             diameter = max(diameter, d[i][j]);
  32. */
  33. }

树形图的最长路径(边无权重)

方法1:

一棵無根樹的「直徑」,就是相離最遠的兩個點的距離。

稍微修改一下計算高度的程式碼,就可以順便計算直徑。

樹的直徑,邊無權重(adjacency matrix)
  1. bool adj[9][9];
  2. int diameter = 0;
  3.  
  4. int DFS(int xint px)  // px是x的父親
  5. {
  6.     int h1 = 0h2 = 0// 紀錄最高與次高的高度
  7.     for (int y=0y<9; ++y)
  8.         if (adj[x][y] && y != px)//记录父亲节点,防止重复访问
  9.         {
  10.             int h = DFS(yx) + 1;
  11.             if (h > h1h2 = h1h1 = h;
  12.             else if (h > h2h2 = h;
  13.         }
  14.     diameter = max(diameterh1 + h2);
  15.     return h1;
  16. }
  17.  
  18. void tree_diameter()
  19. {
  20.     diameter = 0;   // 初始化
  21.  
  22.     int root = 0;   // 隨便選一個樹根
  23.     DFS(rootroot);
  24.     cout << "樹的直徑是" << diameter;
  25. }

一棵樹的各種直徑一定會相交在同一點(同一群點)。

1.反證法。現在有兩條分開的直徑,可是一棵樹上各點都得連通,所以這兩條分開的直徑,中間一定有某處互相連接,一旦連接起來,勢必變成更長的直徑,矛盾。故所有直徑必相交。2.反證法。現在已有兩條直徑相交在某一點,如果另外一條直徑與這兩條直徑相交在另一點,勢必變成更長的直徑,矛盾。故所有直徑必相交在同一點(同一群點)。

方法二:

在一个迷宫中找距离最长的两个点。迷宫可以看作是一个无根树,因此,这个问题等价与在一个树形图中找最远的两个节点,也叫做这个图的直径。

迷宫、树形图有个很好的特点:任意两个节点之间的距离就是这两点之间的最短路径、也是两个节点的最长路径,也可以说任意两个节点之间的距离一定。基于这个想法,可以很快想到:穷举每个点对,计算其距离,取最大值,即可。这个计算量比较大,思想上可行,实践起来,时间代价有点不靠谱。查了下,已经有好的解决方案了:

1 取任意节点作为起点,找出到该点最远的点,记为A;

2 以点A为起点,找出到该点最远的点,记为B;

AB之间的距离,就是图中距离最远的两个点的距离(这样的点对可能有多个,但最大距离值只有一个)。

因此,两次dfs即可搞定。也可以用bfs

代码如下:

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

 

int m,n;

int f[4][2] = {

{0,1},{1,0},{0,-1},{-1,0}};

char map[1002][1002];

bool flag[1002][1002];

 

int max,step,maxM,maxN;

int si,sj;

 

void dfs(int i,int j)

{

    int ii,a,b;

    for(ii=0;ii<4;ii++)

    {

        a = i+ f[ii][0];

        b = j+ f[ii][1];

        if(a>=0 && a<m && b>=0 && b<n && map[a][b]=='.' && flag[a][b])

        {

            step++;

            flag[a][b] = false;

            if(max < step)

            {

                max = step;

                maxM = a;

                maxN = b;

            }

            dfs(a,b);

            flag[a][b] = true;

            step--;

        }

    }

}

int main()

{

    int t,i,j;

    scanf("%d",&t);

    while(t--)

    {

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

        si = -1;

        for(i=0;i<m;i++)

        {

            scanf("%s",map[i]);

            if(si==-1)

                for(j=0;j<n;j++)

                    if(map[i][j]=='.')

                    {

                        si = i;

                        sj = j;

                        break;;

                    }

        }

        

        memset(flag, true, sizeof(flag));

        flag[si][sj] = false;

        max = 0;

        step = 0;

        dfs(si,sj);

        

        memset(flag, true, sizeof(flag));

        flag[maxM][maxN] = false;

        max = 0;

        step = 0;

        dfs(maxM, maxN);

        

        printf("Maximum rope length is %d.\n",max);

    }

    system("pause");

    return 0;

}

如果边有权重的话,感觉着两个算法也能正常工作

你可能感兴趣的文章
OpenLDAP for Windows 安装手册(2.4.26版)
查看>>
图文介绍openLDAP在windows上的安装配置
查看>>
Pentaho BI开源报表系统
查看>>
Pentaho 开发: 在eclipse中构建Pentaho BI Server工程
查看>>
JSP的内置对象及方法
查看>>
android中SharedPreferences的简单例子
查看>>
android中使用TextView来显示某个网址的内容,使用<ScrollView>来生成下拉列表框
查看>>
andorid里关于wifi的分析
查看>>
Spring MVC和Struts2的比较
查看>>
Hibernate和IBatis对比
查看>>
Spring MVC 教程,快速入门,深入分析
查看>>
Android 的source (需安装 git repo)
查看>>
Commit our mod to our own repo server
查看>>
LOCAL_PRELINK_MODULE和prelink-linux-arm.map
查看>>
Simple Guide to use the gdb tool in Android environment
查看>>
Netconsole to capture the log
查看>>
Build GingerBread on 32 bit machine.
查看>>
How to make SD Card world wide writable
查看>>
Detecting Memory Leaks in Kernel
查看>>
Linux initial RAM disk (initrd) overview
查看>>