<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
    原題:

    Command Network

    Description

    After a long lasting war on words, a war on arms finally breaks out between littleken’s and KnuthOcean’s kingdoms. A sudden and violent assault by KnuthOcean’s force has rendered a total failure of littleken’s command network. A provisional network must be built immediately. littleken orders snoopy to take charge of the project.

    With the situation studied to every detail, snoopy believes that the most urgent point is to enable littenken’s commands to reach every disconnected node in the destroyed network and decides on a plan to build a unidirectional communication network. The nodes are distributed on a plane. If littleken’s commands are to be able to be delivered directly from a node A to another node B, a wire will have to be built along the straight line segment connecting the two nodes. Since it’s in wartime, not between all pairs of nodes can wires be built. snoopy wants the plan to require the shortest total length of wires so that the construction can be done very soon.

    Input

    The input contains several test cases. Each test case starts with a line containing two integer N (N ≤ 100), the number of nodes in the destroyed network, and M (M ≤ 104), the number of pairs of nodes between which a wire can be built. The next N lines each contain an ordered pair xi and yi, giving the Cartesian coordinates of the nodes. Then follow M lines each containing two integers i and j between 1 and N (inclusive) meaning a wire can be built between node i and node j for unidirectional command delivery from the former to the latter. littleken’s headquarter is always located at node 1. Process to end of file.

    Output

    For each test case, output exactly one line containing the shortest total length of wires to two digits past the decimal point. In the cases that such a network does not exist, just output ‘poor snoopy’.


    一開始沒仔細讀題,一看以為是最小生成樹呢,結果Krusal算法上去WA了,Prim算法也WA,修修改改一直WA,第二天發現本題是要在有向圖上面構造最小樹形圖。

    按照著名的Zhu-Liu算法,仔細實現了一邊,終于AC了。
    按照我的理解總結下該算法,該算法對每個結點,除根節點外尋找最小入邊,
    1)如果這些入邊不構成環,那么容易證明這些邊構成最小樹形圖。
    證明:設加上根節點r一共N個點,那么一共有N-1條邊,證明從r能到每個點,若存在一點v,使得從r到v沒有路徑,那么,假設從v反向回退必然構成環,因為每個點除了r都有入邊,如果不構成環,該路徑可以無窮大。
    2)如果存在環,我們把環收縮成一個點,更新相應的入邊和出邊,得到新的圖G',使得原問題在G'中等效:
    怎么收縮呢?
    假設我們把環收縮成環上的任意一點v,所有進環的邊和出環的邊自動變成v的邊(如果已有,取長度最短的),其余點標記為刪除,更新不在環上的所有點進入該環的長度cost為cost-cost(prev[x],x);其中點x為進入環的邊在環上的端點。出邊保持不變。

    這里為什么這么更新?因為這樣更新使得我們的算法在新圖上是等效的。任何環的解決后意味著在新圖里面得為改收縮后的點尋找新的入邊,而實際的花費應該是新的入邊減去原有的入邊長度,我們的算法在找到環的時候就把環上所有的邊的長度計算在花費內了.而對出邊是沒有影響的。


    到這算法的框架基本出來了。當為某點沒找到入邊的時候,意味著無解。為了加快無解的偵測,我們先運行一遍DFS搜索,假如從根節點出發,可觸及的節點數小于N-1(不含r)則意味著無解。反之,肯定有解。
    為什么?
    因為如果可觸及數小于N-1,意味著某點是不可觸及的,也就是原圖不是弱連通。對該點來說不存在從r到它的路徑。反之,從r到某點都有一條路徑,沿著該路徑就能找到結點的入邊。


    第二個問題是,如何快速偵測環呢?
    我使用了一個不相交集。回憶Krusal的算法實現里面也是使用不相交集來避免找產生環的最小邊。

    下面是我的代碼:

    // 3164.cpp : Defines the entry point for the console application.
    //

    #include 
    <iostream>
    #include 
    <cmath>


    using namespace std;

    typedef 
    struct _Point
    {

        
    double x;
        
    double y;

        
    double distanceTo(const struct _Point& r)
        {
              
    return sqrt((x-r.x)*(x-r.x)+(y-r.y)*(y-r.y));

        }

    }Point;



    const int MAX_V=100;
    const int MAX_E=10000;
    const double NO_EDGE=1.7976931348623158e+308;

    Point vertexes[MAX_V]
    ={0};
    int parents[MAX_V]={0};
    int ranks[MAX_V]={0};
    double G[MAX_V][MAX_V]={0};
    bool visited[MAX_V]={0};
    bool deleted[MAX_V]={0};
    int prev[MAX_V]={0};

    int nVertex=0;
    int nEdge=0;




    int u_find(int a)
    {
        
    if(parents[a]==a)return a;
        parents[a]
    =u_find(parents[a]);
        
    return parents[a];
    }
    void u_union(int a,int b)
    {
        
    int pa=u_find(a);
        
    int pb=u_find(b);
        
    if(ranks[pa]==ranks[pb])
        {
            ranks[pa]
    ++;
            parents[pb]
    =pa;
        }
    else if(ranks[pa]<ranks[pb])
        {
            parents[pa]
    =pb;
        }
        
    else
        {
            parents[pb]
    =pa;
        }
    }

    void DFS(int v,int& c)
    {

        visited[v]
    =true;
        
    for(int i=1;i<nVertex;i++)
        {
            
    if(!visited[i]&&G[v][i]<NO_EDGE)
            {
                c
    +=1;

                DFS(i,c);
            }

        }

    }



    void doCycle(int s,int t,double& cost)
    {
        memset(visited,
    0,sizeof(bool)*nVertex);
        
    int i=s;
        
    do
        {
            visited[i]
    =true;
            cost
    +=G[prev[i]-1][i];
            
    //cout<<"from "<<(prev[i]-1)<<" to "<<i<<" (cycle)"<<" weight:"<<G[prev[i]-1][i]<<endl;
            i=prev[i]-1;

        }
    while(i!=s);


        
    do
        {
            

            
    for(int k=0;k<nVertex;k++)
            {
                
    if(!deleted[k]&&!visited[k])
                {
                
                    
    if(G[k][i]<NO_EDGE)
                    {
                        
    if(G[k][i]-G[prev[i]-1][i]<G[k][s])
                        {


                            G[k][s]
    =G[k][i]-G[prev[i]-1][i];
                            
    //cout<<"1.update ["<<k<<","<<s<<"] at "<<i<<" as "<<G[k][s]<<endl;
                        }
                        

                    }
                    
    if(G[i][k]<NO_EDGE)
                    {
                        
    if(G[i][k]<G[s][k])
                        {

                            G[s][k]
    =G[i][k];
                            
    //cout<<"2.update ["<<s<<","<<k<<"] at "<<i<<" as "<<G[s][k]<<endl;
                        }
                        
                    }
                }
            }


            
    if(i!=s)
            {
                deleted[i]
    =true;
                
    //cout<<"mark "<<i<<" as deleted"<<endl;
            }
            i
    =prev[i]-1;


        }
    while(i!=s);



    }




    int main(void)
    {



        
        
    while(cin>>nVertex>>nEdge)
        {

            
    int s,t;

            
    int nv=0;
            
    bool cycle=0;
            
    double cost=0;
            memset(vertexes,
    0,sizeof(vertexes));
            memset(visited,
    0,sizeof(visited) );

            memset(deleted,
    0,sizeof(deleted));
            memset(G,
    0,sizeof(G));
            memset(prev,
    0,sizeof(prev));


            memset(ranks,
    0,sizeof(ranks));

            memset(parents,
    0,sizeof(parents));

            
    for(int i=0;i<nVertex;i++)
            {

                cin
    >>vertexes[i].x>>vertexes[i].y;
                parents[i]
    =i;
                
    for(int j=0;j<nVertex;j++)
                {
                    G[i][j]
    =NO_EDGE;
                }

            }
            
    for(int i=0;i<nEdge;i++)
            {

                cin
    >>s>>t;
                
    if(t==1||s==t)continue;
                G[s
    -1][t-1]=vertexes[s-1].distanceTo(vertexes[t-1]);

            }



            DFS(
    0,nv);
            
    if(nv<nVertex-1)
            {

                cout
    <<"poor snoopy"<<endl;
                
    continue;
            }



            
    do {
                cycle
    =false;
                
    for(int i=0;i<nVertex;i++){parents[i]=i;}
                memset(ranks,
    0,sizeof(bool)*nVertex);
            

                
    for (int i = 1; i < nVertex; i++) {
                    
    double minimum=NO_EDGE;
                    
    if(deleted[i])continue;
                    
    for(int k=0;k<nVertex;k++)
                    {
                        
    if(!deleted[k]&&minimum>G[k][i])
                        {
                            prev[i]
    =k+1;
                            minimum
    =G[k][i];
                        }
                    }
                    
    if(minimum==NO_EDGE)
                    {
                    

                        
    throw 1;
                    }
                    
    if (u_find(prev[i]-1== u_find(i)) {
                        doCycle(prev[i]
    -1,i, cost);
                        cycle 
    = true;
                        
    break;
                    }
                    
    else
                    {
                        u_union(i,prev[i]
    -1);
                    }

                }


            } 
    while (cycle);

            
    for (int i = 1; i < nVertex; i++) {
                
    if(!deleted[i])
                {
                    cost
    +=G[prev[i]-1][i];
                    
    //cout<<"from "<<(prev[i]-1)<<" to "<<i<<" weight:"<<G[prev[i]-1][i]<<endl;
                }

            }

            printf(
    "%.2f\n",cost);


        }


    }



    posted on 2009-04-24 16:39 DoubleH 閱讀(2426) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 成人超污免费网站在线看| 91精品全国免费观看含羞草| free哆啪啪免费永久| 亚洲AV综合色区无码另类小说| 成人精品国产亚洲欧洲| 欧洲黑大粗无码免费 | 亚洲av成人一区二区三区在线观看| 亚洲国产人成在线观看| 免费能直接在线观看黄的视频 | 久久久无码精品亚洲日韩蜜臀浪潮| 久久久WWW免费人成精品| 亚洲av区一区二区三| 亚洲aⅴ无码专区在线观看春色| 在线jlzzjlzz免费播放| 亚洲欧美一区二区三区日产| 最近免费中文字幕大全| 麻豆狠色伊人亚洲综合网站| 啦啦啦高清视频在线观看免费| 亚洲中文字幕无码av在线| 香蕉97超级碰碰碰免费公| 亚洲不卡影院午夜在线观看| 免费高清在线爱做视频| 爱情岛论坛免费视频| 亚洲伊人成无码综合网| 国产一级高青免费| 亚洲人成电影福利在线播放| 无码精品人妻一区二区三区免费看 | 2015日韩永久免费视频播放 | 国产精品成人免费视频网站京东| 亚洲成人免费电影| 妞干网在线免费观看| 人成免费在线视频| 日韩精品亚洲人成在线观看| 成在人线AV无码免费| 四虎永久在线精品免费一区二区| 亚洲中文字幕无码一久久区| 中文字幕免费视频一| 久久精品熟女亚洲av麻豆| 亚洲人成人无码网www电影首页 | 亚洲Av永久无码精品黑人| 亚洲av麻豆aⅴ无码电影|