• <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| 亚洲午夜福利精品久久| 久久久久综合国产欧美一区二区| 精品久久国产一区二区三区香蕉| 久久天天躁狠狠躁夜夜av浪潮| 久久性精品| 久久香综合精品久久伊人| 国产成人99久久亚洲综合精品| 午夜精品久久久久久久无码| 中文字幕乱码人妻无码久久| 麻豆AV一区二区三区久久 | 久久激情五月丁香伊人| 久久伊人五月丁香狠狠色| 91精品国产高清久久久久久91| 久久人与动人物a级毛片| www久久久天天com| 亚洲а∨天堂久久精品9966| 欧美精品久久久久久久自慰| 久久亚洲AV永久无码精品| 久久亚洲精精品中文字幕| 久久免费99精品国产自在现线| 久久国产精品77777| 欧美大香线蕉线伊人久久| 久久国产视频99电影| 国产婷婷成人久久Av免费高清| 日韩欧美亚洲国产精品字幕久久久 | 色99久久久久高潮综合影院| 久久精品国产亚洲精品2020| 国内精品伊人久久久久妇| 狠狠综合久久综合中文88| 国产精品一区二区久久国产| 最新久久免费视频| 久久久久久久综合日本| 麻豆精品久久精品色综合| 午夜天堂av天堂久久久| 午夜久久久久久禁播电影| 人妻丰满?V无码久久不卡| 色综合合久久天天给综看| 久久综合九色综合久99|