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

            題目描述: 

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

            算法分析:

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

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

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

            #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 西月弦 閱讀(409) 評論(0)  編輯 收藏 引用 所屬分類: 解題報告
            国产亚洲精品自在久久| 少妇久久久久久被弄到高潮| 亚洲午夜久久久影院伊人| 看久久久久久a级毛片| 国产一级持黄大片99久久| 精品久久久久中文字幕一区| 日日狠狠久久偷偷色综合0| 久久发布国产伦子伦精品 | 成人国内精品久久久久影院VR| 久久99精品久久久久久噜噜| 免费无码国产欧美久久18| 久久狠狠色狠狠色综合| 久久免费香蕉视频| 精品久久久久久久久午夜福利| 久久久91人妻无码精品蜜桃HD | 午夜久久久久久禁播电影| 狠狠色丁香婷综合久久| 人妻无码αv中文字幕久久| 狠狠综合久久综合中文88 | 一级A毛片免费观看久久精品| 亚洲∧v久久久无码精品| 久久免费视频一区| 中文字幕久久欲求不满| 激情伊人五月天久久综合| 国产一区二区久久久| 久久久久人妻精品一区三寸蜜桃 | 久久青青草原亚洲av无码app| 要久久爱在线免费观看| 久久成人18免费网站| 99久久久久| 成人a毛片久久免费播放| 国产精品美女久久久| 精品久久久久久中文字幕人妻最新 | 品成人欧美大片久久国产欧美... 品成人欧美大片久久国产欧美 | 久久久久久曰本AV免费免费| 久久人人爽人人爽人人片AV麻豆| 久久99国产精品久久久| AV无码久久久久不卡网站下载 | 亚洲欧洲久久久精品| 久久久久亚洲爆乳少妇无| 久久久久久久久久免免费精品|