• <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>

            【AHOI2013復仇】s-t第K短簡單路問題

            Posted on 2012-09-23 14:28 Mato_No1 閱讀(1531) 評論(0)  編輯 收藏 引用 所屬分類: 經典問題的模型 、搜索SCOI
            [SCOI2007 kshort]
            求圖的s-t第K短簡單路問題,若有長度相同的,字典序小的優先。

            首先,由于是簡單路,所以A*是不能做的,因為有可能有兩條s-i(i為某個中間點)路P1和P2,P1比P2短,但由于P1到達的頂點與P2不同,導致最終沿P1到達t的路徑長度長于沿P2到達t的(甚至有可能沿P1根本到不了t)。然后,如果直接用DFS,由于要求的是第K優解,而不是最優解,所以不能使用最優性剪枝(包括分支限界),因此專門為最優性剪枝服務的“改變搜索順序”技巧也不能使用了,因此,能夠使用的只有可行性剪枝,而本題的數據范圍使得這種算法必然TLE。

            正解是一種由迭代加深思想擴展得到的“迭代變優”DFS。設置一個路徑長度上限Z,搜索s到t的所有簡單路,在搜索過程中,遇到長度大于Z的路徑就停止(剪枝),然后,若得到路徑不足K條,則增加Z的值,重新開始搜索,直到得到的路徑總數大于等于K條為止。這里可以進行啟發式的優化,設g[i]為點i到t的最短路長度,則搜索過程中,假設目前搜到點i,則(目前路徑長度+g[i])是對整條路徑最短長度的樂觀估計,如果這個值超過了Z,就可以剪枝,但在剪枝之前要記下這個超過了Z的啟發值,取其中最小的作為下一次迭代的Z值。那么對于字典序腫么辦?可以在搜索過程中,強制先搜編號小的結點,這樣得到的s-t路徑必然是字典序遞增的。另外只要求出第K條路徑,搜索就可以終止,因為容易證明,題目要求的第K短的路徑一定已經求出來了(只不過不一定是最后一條而已),找到即可。此外,在搜索過程中不要忘了可行性剪枝,就是如果沿目前搜到的路徑已經到不了t了,剪枝。

            “迭代變優”DFS,就是設置一個解的評價值的上限(最小值)或下限(最大值),在搜索過程中,如果實際評價值(或者啟發值,如果可以加啟發式優化的話)越過這個限制,則剪枝。在一次搜索后,如果沒有得到符合要求的解,就將該限制值設為本次搜索過程中越界“越”得最近的那個值,重新開始搜索,直到找到所需要的解或者發現無解(如果一次搜索中沒有發生越界,卻仍然沒有找到解)為止。其應用主要體現在兩個方面:(1)搜索樹過深甚至無限深,但所需求的那個解卻不深的情況;(2)求第K優解的情況。

            代碼:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <string.h>
            #include 
            <algorithm>
            using namespace std;
            #define re(i, n) for (int i=0; i<n; i++)
            #define re1(i, n) for (int i=1; i<=n; i++)
            #define re2(i, l, r) for (int i=l; i<r; i++)
            #define re3(i, l, r) for (int i=l; i<=r; i++)
            #define rre(i, n) for (int i=n-1; i>=0; i--)
            #define rre1(i, n) for (int i=n; i>0; i--)
            #define rre2(i, r, l) for (int i=r-1; i>=l; i--)
            #define rre3(i, r, l) for (int i=r; i>=l; i--)
            const int MAXN = 51, MAXK = 201, MAXM = 3000, INF = ~0U >> 2;
            struct edge {
                
            int a, b, w, pre, next;
            } E[MAXM 
            + MAXN], E0[MAXM + MAXN];
            struct edge0 {
                
            int a, b, w;
                
            bool operator< (edge0 e0) const {return b < e0.b;}
            } _E[MAXM];
            int n, m, s, t, K, dist[MAXN], Q[MAXN + 1];
            int Z, Z0, vst0[MAXN], _FL, len0, X00[MAXN], No, len[MAXK], X0[MAXK][MAXN], sum0[MAXK], reslen, res[MAXN];
            bool vst[MAXN], res_ex = 0;
            void init_d()
            {
                re(i, n) E[i].pre 
            = E[i].next = E0[i].pre = E0[i].next = i; m = n;
            }
            void add_edge(int a, int b, int w)
            {
                E[m].a 
            = a; E[m].b = b; E[m].w = w; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m;
                E0[m].a 
            = b; E0[m].b = a; E0[m].w = w; E0[m].pre = E0[b].pre; E0[m].next = b; E0[b].pre = m; E0[E0[m].pre].next = m++;
            }
            void init()
            {
                
            int m0; scanf("%d%d%d%d%d"&n, &m0, &K, &s, &t); init_d(); s--; t--;
                re(i, m0) {scanf(
            "%d%d%d"&_E[i].a, &_E[i].b, &_E[i].w); _E[i].a--; _E[i].b--;}
                sort(_E, _E 
            + m0);
                re(i, m0) add_edge(_E[i].a, _E[i].b, _E[i].w);
            }
            void prepare()
            {
                re(i, n) {vst[i] 
            = 0; dist[i] = INF;} vst[t] = 1; dist[t] = 0; Q[0= t;
                
            int x, y, d0, d1;
                
            for (int front=0, rear=0!(!front && rear==|| front==rear+1); front==? front=0 : front++) {
                    x 
            = Q[front]; d0 = dist[x];
                    
            for (int p=E0[x].next; p != x; p=E0[p].next) {
                        y 
            = E0[p].b; d1 = d0 + E0[p].w;
                        
            if (d1 < dist[y]) {
                            dist[y] 
            = d1;
                            
            if (!vst[y]) {vst[y] = 1; Q[rear==? rear=0 : ++rear] = y;}
                        }
                    }
                    vst[x] 
            = 0;
                }
            }
            void dfs(int x, int sum)
            {
                
            if (x == t) {
                    
            if (sum <= Z) {sum0[No] = sum; len[No] = len0; re(i, len0) X0[No][i] = X00[i]; No++if (No == K) res_ex = 1;}
                    
            else if (sum < Z0) Z0 = sum;
                    
            return;
                } 
            else {
                    
            int h0 = sum + dist[x];
                    
            if (h0 > Z) {if (h0 < Z0) Z0 = h0; return;}
                    vst0[x] 
            = ++_FL; Q[0= x; int _x, _y;
                    
            for (int front=0, rear=0; front<=rear; front++) {
                        _x 
            = Q[front];
                        
            for (int p=E[_x].next; p != _x; p=E[p].next) {
                            _y 
            = E[p].b;
                            
            if (!vst[_y] && vst0[_y] != _FL) {vst0[_y] = _FL; Q[++rear] = _y;}
                        }
                    }
                    
            if (vst0[t] != _FL) return;
                    
            for (int p=E[x].next; p != x; p=E[p].next) {
                        _y 
            = E[p].b;
                        
            if (!vst[_y]) {vst[_y] = 1; X00[len0++= _y; dfs(_y, sum + E[p].w); if (res_ex) returnelse {len0--; vst[_y] = 0;}}
                    }
                }
            }
            void solve()
            {
                Z 
            = dist[s]; int No0 = 0; _FL = 0;
                
            while (1) {
                    Z0 
            = INF; No = 0; re(i, n) {vst[i] = 0; vst0[i] = 0;}
                    vst[s] 
            = 1; len0 = 1; X00[0= s; dfs(s, 0);
                    
            if (res_ex) {
                        No0 
            = K - No0;
                        re(i, K) 
            if (sum0[i] == Z) {No0--if (!No0) {reslen = len[i]; re(j, len[i]) res[j] = X0[i][j];}}
                        
            break;
                    } 
            else if (Z0 == INF) breakelse {No0 = No; Z = Z0;}
                }
            }
            void pri()
            {
                
            if (res_ex) {
                    printf(
            "%d", res[0+ 1);
                    re2(i, 
            1, reslen) printf("-%d", res[i] + 1);
                    puts(
            "");
                } 
            else puts("No");
            }
            int main()
            {
                init();
                prepare();
                solve();
                pri();
                
            return 0;
            }


            久久人人爽人爽人人爽av| 久久久无码精品午夜| 亚洲va久久久久| 狠狠久久综合伊人不卡| 精品久久久久久无码专区| 久久久久久综合网天天| 精品久久久久成人码免费动漫 | 久久人人爽人人爽人人AV东京热| 91麻精品国产91久久久久| 精品免费tv久久久久久久| 91精品国产9l久久久久| 久久精品国产精品亚洲毛片 | 久久精品国产亚洲精品2020 | 好久久免费视频高清| AV色综合久久天堂AV色综合在 | 久久亚洲美女精品国产精品| 蜜臀久久99精品久久久久久小说 | 大美女久久久久久j久久| 91精品无码久久久久久五月天| 91久久精品电影| 日韩欧美亚洲综合久久影院Ds| 亚洲欧美久久久久9999| 一本色道久久HEZYO无码| 久久精品国产亚洲AV大全| 伊人丁香狠狠色综合久久| 久久精品国产一区二区三区不卡| 婷婷久久综合| 久久久久久夜精品精品免费啦| 婷婷久久综合九色综合98| 久久e热在这里只有国产中文精品99| 内射无码专区久久亚洲| 亚洲精品乱码久久久久久中文字幕 | 国产精品欧美亚洲韩国日本久久| 久久久91人妻无码精品蜜桃HD| 久久精品国产免费观看| 亚洲综合婷婷久久| 99精品久久精品一区二区| 国产精品永久久久久久久久久 | 狠狠色综合网站久久久久久久| 久久无码中文字幕东京热| 99久久精品国产一区二区蜜芽|