• <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>
            算法學社
            記錄難忘的征途
            posts - 141,comments - 220,trackbacks - 0

            題目描述: 

                求N<3,000個點的稠密圖的最小生成樹的每條邊的最佳替換邊。

            算法分析:

                先求最小生成樹,這個不用說了。

                dp[i][j]表示,i和i的子孫到j的最小邊(不計算生成樹的邊)。
                這個可以通過樹形DP(中序遍歷 + 后序遍歷)求的。
                注意j不能是i的子孫,這個要通過時間戳來判斷。

                同時用一個優先級隊列,把這樣的邊都存起來。在回溯過程中僅用O(logE)的時間就可以判斷最佳邊了。
                復雜度O(V*V*logE)
                寫起來不太好寫,想到不難,但是復雜度不好把握。

            #include<iostream>
            #include<cstdio>
            #include<queue>
            using namespace std;
            // graph
            const int V = 3000+10;
            int n,m, num[V][V];
            // prim
            int low[V], vis[V], P[V], G[V][V];
            const int inf = ~0u>>2;
            int prim(){
                for(int i=0;i<n;i++) vis[i] = 0, low[i] = inf, P[i] = -1;
                for(int i=0;i<n;i++)
                    for(int j=0;j<n;j++)
                        G[i][j] = 0;
                P[0] = low[0] = 0;
                int ans = 0;
                for(int i=0;i<n;i++){
                    int s , mn = inf;
                    for(int j= 0; j< n; j++) if(!vis[j] && low[j] < mn){
                        mn = low[j]; s = j;
                    }
                    vis[s] = 1;
                    ans += mn;
                    if(P[s] != s) G[s][P[s]] = G[P[s]][s] = mn;
                    for(int v = 0; v < n; v++) if(num[s][v])
                        if(!vis[v] && low[v] > num[s][v] )
                            low[v] = num[s][v], P[v] =s;
                }
                return ans;
            }
            // dfs
            template <typename T> inline void chkmin(T &a, const T b){if(a>b)a=b;};
            int pre[V],snd[V], tm, __ans[V][V];
            typedef pair<intint > node;
            priority_queue<node, vector<node> , greater <node> > Q[V];
            int temp[V][V];
            void dfs1(int u,int f){
                pre[u] = tm ++;
                for(int v = 0; v< n; v++) if(G[u][v] && pre[v] == -1)
                    dfs1(v,u);
                snd[u] = tm ++;
            }
            #define ff first
            #define ss second
            void dfs(int u,int f) {
                while(!Q[u].empty()) Q[u].pop();
                for(int v=0;v<n;v++) if( G[u][v] && v!=f) {
                    dfs(v,u);
                    if(!Q[v].empty()) __ans[u][v] = __ans[v][u] = Q[v].top().ff;
                    while(!Q[v].empty()) {
                        int val = Q[v].top().ff;
                        int to = Q[v].top().ss;
                        chkmin(temp[u][to],val);
                        Q[v].pop();
                    }
                }
                for(int i=0;i<n;i++) if(i!=f){
                    chkmin(temp[u][i],num[u][i]);
                }
                for(int v=0;v<n;v++) if(temp[u][v] != inf ) {
                    if(pre[v] >= pre[u] && snd[v] <= snd[u]) continue;
                    Q[u].push(make_pair(temp[u][v],v));
                }
            }
            void work(){
                tm = 0;
                for(int i=0;i<n;i++)
                    pre[i] = -1;
                dfs1(0,0);
                for(int i=0;i<n;i++)
                    for(int j=0;j<n;j++)
                        temp[i][j] = __ans[i][j] = inf;
                dfs(0,0);
            }
            // main
            int main(){
                while(~scanf("%d%d",&n,&m) && n) {
                    int u,v,c;
                    for(int i=0;i<n;i++)
                        for(int j=0;j<n;j++) num[i][j] = inf;
                    for(int i=0;i<m;i++) {
                        scanf("%d%d%d",&u,&v,&c);
                        num[u][v] = num[v][u] = c;
                    }
                    int t = prim();
                    work();
                    // query
                    int q; double ans = 0;
                    scanf("%d",&q);
                    for(int oo=0;oo<q;oo++){
                        scanf("%d%d%d",&u,&v,&c);
                        if(!G[u][v])
                            ans += t;
                        else if(c <= __ans[u][v])
                            ans += t - G[u][v] + c;
                        else ans += t - G[u][v] + __ans[u][v];
                    }
                    printf("%.4lf\n", ans/q);
                }
                return 0;
            }
            posted on 2012-07-30 13:46 西月弦 閱讀(413) 評論(0)  編輯 收藏 引用 所屬分類: 解題報告
            香蕉久久一区二区不卡无毒影院 | 无码伊人66久久大杳蕉网站谷歌 | 国产成人精品久久二区二区| 国产精品久久久久9999高清| 久久久久综合中文字幕| 久久亚洲sm情趣捆绑调教| 91精品国产综合久久婷婷 | 久久午夜羞羞影院免费观看| 97久久精品人人做人人爽| 囯产极品美女高潮无套久久久| 久久99国产精品久久99| 99久久精品免费看国产一区二区三区| 久久精品国产免费一区| 人妻无码久久一区二区三区免费| 狠狠精品干练久久久无码中文字幕| 久久久久久久久波多野高潮| 久久99精品久久久久久齐齐| 国产精品久久久久影视不卡| 亚洲国产精品无码久久SM | 久久香蕉国产线看观看猫咪?v| 国产精品久久国产精品99盘 | 国产精品欧美久久久天天影视 | 91久久精品国产91性色也| 国产精品美女久久久| 久久精品国产亚洲av影院| 久久午夜夜伦鲁鲁片免费无码影视| 精品九九久久国内精品| 久久久久久亚洲Av无码精品专口| 蜜桃麻豆WWW久久囤产精品| 女同久久| 亚洲欧美日韩精品久久亚洲区 | 亚洲AV日韩AV永久无码久久| 2021国内久久精品| 国产香蕉久久精品综合网| 日产久久强奸免费的看| 香蕉aa三级久久毛片| 久久婷婷五月综合成人D啪| 欧美精品乱码99久久蜜桃| A级毛片无码久久精品免费| 久久国产精品无码HDAV| 精品熟女少妇a∨免费久久|