• <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 西月弦 閱讀(411) 評論(0)  編輯 收藏 引用 所屬分類: 解題報告
            国产美女久久久| 久久久久无码精品国产| 久久久久久av无码免费看大片| 国产福利电影一区二区三区久久久久成人精品综合 | 国产激情久久久久影院小草| 久久精品成人| 久久久久女人精品毛片| 精品久久久久久无码中文字幕 | 91精品婷婷国产综合久久| 精品国产日韩久久亚洲| 国产精品岛国久久久久| 久久国产欧美日韩精品免费| 久久99国产精品尤物| 久久久精品久久久久久| 久久久久国产精品熟女影院| 久久性精品| 国产精品成人99久久久久91gav| 亚洲午夜久久久久久久久久| 久久久久久极精品久久久| 丰满少妇人妻久久久久久 | 久久人人爽人人人人爽AV| 一本大道久久a久久精品综合| 99久久夜色精品国产网站| 久久精品无码一区二区三区免费| 欧美一区二区三区久久综| 亚洲а∨天堂久久精品| 久久强奷乱码老熟女网站| 久久成人影院精品777| 久久久久久夜精品精品免费啦| 久久亚洲sm情趣捆绑调教| 伊人色综合九久久天天蜜桃| 久久精品女人天堂AV麻| 久久国产成人午夜AV影院| 国产女人aaa级久久久级| 久久综合中文字幕| 久久99免费视频| 亚洲天堂久久精品| 久久精品国产99国产精品| 久久露脸国产精品| 久久午夜无码鲁丝片秋霞| 伊人久久精品无码二区麻豆|