• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            The Fourth Dimension Space

            枯葉北風寒,忽然年以殘,念往昔,語默心酸。二十光陰無一物,韶光賤,寐難安; 不畏形影單,道途阻且慢,哪曲折,如渡飛湍。斬浪劈波酬壯志,同把酒,共言歡! -如夢令

            pku 3164 最小樹形圖(Zhu-Liu Algorithm)

            所謂的最小樹形圖,就是讓你在一個有向圖中找一個根和由根擴展出來的一顆有向的生成樹,并且使這棵樹的權值最小。
            令人欣喜的是,這個算法是由中國人提出來的,這也是我正式學習的第一個中國人提出來的算法^_^

            最小樹形圖算法
            (Zhu-Liu Algorithm)

            1.       設最小樹形圖的總權值為cost,置cost0

            2.       除源點外,為其他所有節點Vi找一條權值最小的入邊,加入集合TT就是最短邊的集合。加邊的方法:遍歷所有點到Vi的邊中權值最小的加入集合T,記pre[Vi]為該邊的起點,mincost[Vi]為該邊的權值。

            3.       檢查集合T中的邊是否存在有向環,有則轉到步驟4,無則轉到步驟5。這里需要利用pre數組,枚舉檢查過的點作為搜索的起點,類似dfs的操作判斷有向環。

            4.       將有向環縮成一個點。設環中有點{Vk1,Vk2,…,Vki}i個點,用Vk代替縮成的點。在壓縮后的圖中,更新所有不在環中的點VVk的距離:

            map[V][Vk] = min {map[V][Vkj]-mincost[Vki]} 1<=j<=i

            map[Vk][V] = min {map[Vkj][V]}           1<=j<=I

            5.       cost加上T中有向邊的權值總和就是最小樹形圖的權值總和。

            源代碼如下:(參考了網上的代碼)
            #include<iostream>
            #include
            <cstring>
            #include
            <cstdio>
            #include
            <cmath>
            using namespace std;

            #define INF 99999999
            #define min( a, b ) ( (a)< (b)?(a): (b) )

            struct point
            {

                
            double x;
                
            double y;
            }
            p[200];

            int pre[200];//記錄該節點的前驅
            double graph[200][200], ans;//圖數組和結果
            bool   visit[110], circle[110];//visit記錄該點有沒有被訪問過,circle記錄改點是不是在一個圈里
            int    n, m, root;//頂點數+邊數+根節點標號

            void dfs( int t )//一個深度優先搜索,搜索出一個最大的聯通空間
            {
                
            int i;
                visit[t]
            = true;
                
            for(i= 1; i<= n; ++i )
                
            {
                    
            if!visit[i] && graph[t][i]!= INF )
                        dfs( i );
                }

            }


            bool check()//這個函數用來檢查最小樹形圖是否存在,即如果存在,那么一遍dfs后,應該可以遍歷到所有的節點
            {
                memset( visit, 
            falsesizeof(visit) );
                dfs( root );
                
                
            forint i= 1; i<= n; ++i )
                
            {
                    
            if!visit[i] ) 
                        
            return false;
                }

                
            return true;
            }


            double dist( int i, int j )
            {
                
            return sqrt( (p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y) );
            }


            int exist_circle()//判斷圖中是不是存在有向圈
            {
                
            int i;
                
            int j;
                root
            = 1; pre[root]= root;
                
            for(i= 1; i<= n; ++i )
                
            {
                    
            if!circle[i] && i!= root )
                    
            {
                        pre[i]
            = i; graph[i][i]= INF;
                        
                        
            for(j= 1; j<= n; ++j )
                        
            {
                            
            if!circle[j] && graph[j][i]< graph[pre[i]][i] )
                                pre[i]
            = j;
                        }

                    }

                }
            //這個for循環負責找出所有非根節點的前驅節點
                for( i= 1; i<= n; ++i )
                
            {
                    
            if( circle[i] ) 
                        
            continue;
                    memset( visit, 
            falsesizeof(visit) );
                    
            int j= i;
                    
            while!visit[j] ) 
                    

                        visit[j]
            = true
                        j
            = pre[j]; 
                    }

                    
            if( j== root )
                        
            continue;
                    
                    
            return j;
                }
            //找圈過程,最后返回值是圈中的一個點
                
                
            return -1;//如果沒有圈,返回-1
            }



            void  update( int t )//縮圈之后更新數據
            {
                
            int i;
                
            int j;
                ans
            += graph[pre[t]][t];
                
            for(i=pre[t]; i!= t; i= pre[i] )
                
            {
                    ans
            += graph[pre[i]][i];
                    circle[i]
            = true;
                }
            //首先把圈里的邊權全部加起來,并且留出t節點,作為外部接口
                
                
            for(i= 1; i<= n; ++i )
                    
            if!circle[i] && graph[i][t]!= INF )
                        graph[i][t]
            -= graph[pre[t]][t];
                
            //上面這個for循環的作用是對t節點做更新操作,為什么要單獨做?你可以看看線面這個循環的跳出條件。
                for(j= pre[t]; j!= t; j= pre[j] )
                    
            forint i= 1; i<= n; ++i )
                    
            {
                        
            if( circle[i] ) 
                            
            continue;
                        
            if( graph[i][j]!= INF )
                        graph[i][t]
            = min( graph[i][t], graph[i][j]- graph[pre[j]][j] );
                        
            //////////////////////////////////////////////////////////////////////////
                        graph[t][i]= min( graph[j][i], graph[t][i] );
                    }

                
            //這個循環對圈中的其他頂點進行更新
            }


            void solve()
            {
                
            int j;
                memset( circle, 
            falsesizeof(circle) );
                
            while( ( j= exist_circle() )!= -1 ) 
                    update( j );
                
                
            for( j= 1; j<= n; ++j )
                    
            if( j!= root && !circle[j] )
                        ans
            += graph[pre[j]][j];
                
                printf(
            "%.2lf\n", ans );
            }


            int main()
            {
                
            int i;
                
            while( scanf("%d%d",&n,&m)!= EOF )
                
            {
                    
            for(i= 0; i<= n; ++i )
                        
            forint j= 0; j<= n; ++j )
                            graph[i][j]
            = INF;
                    
                    
            for(i= 1; i<= n; ++i )
                        scanf(
            "%lf%lf",&p[i].x, &p[i].y );
                    
                    
            for(i= 0; i< m; ++i )
                    
            {
                        
            int a, b;
                        scanf(
            "%d%d",&a,&b);
                        graph[a][b]
            = dist( a, b );
                    }

                    
                    root
            = 1
                    ans
            = 0;
                    
            if!check() ) 
                        printf(
            "poor snoopy\n");
                    
            else  
                        solve();
                }

                
                
            return 0;
            }



            posted on 2009-10-29 19:38 abilitytao 閱讀(2175) 評論(2)  編輯 收藏 引用

            評論

            # re: pku 3164 最小樹形圖(Zhu-Liu Algorithm) 2009-10-30 11:58 淘寶網首頁

            學習!學習~~  回復  更多評論   

            # re: pku 3164 最小樹形圖(Zhu-Liu Algorithm) 2009-11-03 16:31 argmax

            這個算法應該叫Chu-Liu-Edmond算法吧!  回復  更多評論   

            亚洲欧美成人久久综合中文网 | 久久成人国产精品一区二区| 精品午夜久久福利大片| 国产亚洲精久久久久久无码77777 国产亚洲精品久久久久秋霞 | 97精品久久天干天天天按摩| 精品一区二区久久| 久久久国产亚洲精品| 一级女性全黄久久生活片免费 | 久久久无码精品亚洲日韩按摩 | 国产AV影片久久久久久| 久久国产乱子伦精品免费强| 久久性精品| 久久久久av无码免费网| 久久天天躁夜夜躁狠狠躁2022| 欧洲成人午夜精品无码区久久| 久久99亚洲综合精品首页| 无码人妻少妇久久中文字幕| 久久精品国产亚洲AV无码偷窥| 久久国产成人亚洲精品影院| 久久久婷婷五月亚洲97号色| 亚洲国产小视频精品久久久三级 | 久久精品aⅴ无码中文字字幕不卡 久久精品aⅴ无码中文字字幕重口 | 欧美午夜A∨大片久久 | 久久综合狠狠综合久久97色| 性欧美丰满熟妇XXXX性久久久 | 亚洲成人精品久久| 热99re久久国超精品首页| 久久久久无码中| 九九久久自然熟的香蕉图片| 无夜精品久久久久久| 国产一级持黄大片99久久| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 精品伊人久久大线蕉色首页| 久久精品国产精品亚洲人人| 久久成人影院精品777| 久久亚洲AV无码精品色午夜| 中文精品久久久久国产网址| 国产成人精品白浆久久69| 国产精品久久久久久久人人看| 欧美久久亚洲精品| 久久久久久久人妻无码中文字幕爆|