• <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找一條權值最小的入邊,加入集合T。T就是最短邊的集合。加邊的方法:遍歷所有點到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 閱讀(2180) 評論(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算法吧!  回復  更多評論   

            亚洲中文久久精品无码ww16| 久久99久久99小草精品免视看| 久久久久免费视频| 少妇人妻综合久久中文字幕| 久久精品毛片免费观看| 精品国产乱码久久久久久浪潮| 日本欧美国产精品第一页久久| 色综合久久久久综合体桃花网| 国产免费福利体检区久久| 亚洲欧美日韩久久精品第一区| 一级做a爰片久久毛片16| 久久午夜福利无码1000合集| 久久精品嫩草影院| 国产精品美女久久福利网站| 亚洲国产精品人久久| 色婷婷综合久久久久中文| 很黄很污的网站久久mimi色 | 国产精品久久久久蜜芽| 日本免费一区二区久久人人澡| 伊人久久大香线蕉精品不卡| 天天久久狠狠色综合| 国产精品99久久精品| 午夜天堂av天堂久久久| 久久综合视频网| 香蕉99久久国产综合精品宅男自 | 久久久久国产日韩精品网站| 色成年激情久久综合| 久久精品九九亚洲精品| 欧美一区二区三区久久综合| 日韩人妻无码一区二区三区久久99 | 久久电影网一区| 精品永久久福利一区二区| 亚洲国产精品18久久久久久| 国产精品美女久久福利网站| 久久午夜夜伦鲁鲁片免费无码影视 | 久久精品成人免费国产片小草| 99久久久精品免费观看国产| 精品久久久无码人妻中文字幕豆芽| 色欲久久久天天天综合网精品| 国色天香久久久久久久小说| 亚洲熟妇无码另类久久久|