• <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復仇】ZJOI2008 騎士 題解

            Posted on 2012-09-01 17:03 Mato_No1 閱讀(1051) 評論(0)  編輯 收藏 引用 所屬分類: 經典問題的模型ZJOI
            原題地址
            本沙茶的第一個無向環套樹模型,紀念一下……

            環套樹,指的是每個連通塊中點數都等于邊數的無向圖(稱為無向環套樹)或者是每個點有且只有一個前趨(稱為內向環套樹)或后繼(稱為外向環套樹)的有向圖,由于這個圖的每個連通塊當中有且只有一個環(注意,可能是自環,即長度為1的環),且這個環上的每個點都可以當作根引出一棵樹,所以叫“環套樹”。

            對于無向環套樹,先將整個圖進行一次DFS,當中如果發現有逆向邊(這條邊第一次被發現必然是作為逆向邊的,也就是起點是終點的后代),就說明找到了這個環,記錄其起點和終點(注意,如果有多個連通塊的話,不能退出,要繼續遍歷完),再不斷上溯(因此在DFS過程中當然要記錄父邊了囧),就可以找到整個環了,然后再以環上的結點為根建樹即可,這樣依次處理每個連通塊。

            對于內向環套樹(外向類似),找環更為簡單,只需要任選一個點,不斷去找它的前趨,同時記錄找到的點序列,直到某個點在序列中出現兩次為止,此時這個點以及序列中它兩次出現的位置中間的所有點,就是環上的點,順序也順便記錄下來,然后樹也不用建了,直接在原圖中找就行了。

            對于這題,由于每個點都有且只有一個后繼,所以是外向環套樹,不過本沙茶更傾向于它的基圖(無向圖,是無向環套樹),然后就是一個DP了囧……

            代碼:
            #include <iostream>
            #include 
            <stdio.h>
            #include 
            <stdlib.h>
            #include 
            <string.h>
            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--)
            #define ll long long
            const int MAXN = 1000010;
            const ll INF = ~0Ull >> 2;
            struct edge {
                
            int a, b, pre, next;
            } E0[MAXN 
            * 3], E[MAXN << 1];
            int n, m0, m, A[MAXN], stk[MAXN], st[MAXN], pr[MAXN], Q[MAXN];
            ll F[MAXN][
            2], res = 0;
            bool vst[MAXN], vst0[MAXN];
            void init_d()
            {
                re(i, n) E0[i].pre 
            = E0[i].next = E[i].pre = E[i].next = i; if (n & 1) m0 = n + 1else m0 = n; m = n;
            }
            void add_edge0(int a, int b)
            {
                E0[m0].a 
            = a; E0[m0].b = b; E0[m0].pre = E0[a].pre; E0[m0].next = a; E0[a].pre = m0; E0[E0[m0].pre].next = m0++;
                E0[m0].a 
            = b; E0[m0].b = a; E0[m0].pre = E0[b].pre; E0[m0].next = b; E0[b].pre = m0; E0[E0[m0].pre].next = m0++;
            }
            void add_edge(int a, int b)
            {
                E[m].a 
            = a; E[m].b = b; E[m].pre = E[a].pre; E[m].next = a; E[a].pre = m; E[E[m].pre].next = m++;
            }
            void init()
            {
                scanf(
            "%d"&n); int x; init_d();
                re(i, n) {
                    scanf(
            "%d%d"&A[i], &x); add_edge0(--x, i);
                }
            }
            void sol0(int x)
            {
                Q[
            0= x; int i, j, front, rear;
                
            for (front=0, rear=0; front<=rear; front++) {
                    i 
            = Q[front];
                    
            for (int p=E0[i].next; p != i; p=E0[p].next) {
                        j 
            = E0[p].b;
                        
            if (!vst0[j]) {Q[++rear] = j; vst0[j] = 1; add_edge(i, j);}
                    }
                }
                rre3(z, rear, 
            0) {
                    i 
            = Q[z];
                    F[i][
            0= 0; F[i][1= A[i];
                    
            for (int p=E[i].next; p != i; p=E[p].next) {
                        j 
            = E[p].b; F[i][0+= F[j][0>= F[j][1? F[j][0] : F[j][1]; F[i][1+= F[j][0];
                    }
                }
            }
            void solve()
            {
                re(i, n) {vst[i] 
            = vst0[i] = 0; st[i] = E0[i].next;} int x, y, tp, x0, y0; bool FF, FF2; ll tmp0, tmp1, tmp00, tmp01, res0;
                re(i, n) 
            if (!vst[i]) {
                    stk[tp 
            = 0= i; vst[i] = 1; FF2 = 0;
                    
            while (tp >= 0) {
                        x 
            = stk[tp]; FF = 0;
                        
            for (int p=st[x]; p != x; p=E0[p].next) {
                            y 
            = E0[p].b;
                            
            if (!vst[y]) {vst[y] = 1; stk[++tp] = y; pr[y] = p; st[x] = E0[p].next; FF = 1break;}
                            
            else if (p != (pr[x] ^ 1&& !FF2) {FF2 = 1; x0 = x; y0 = y;}
                        }
                        
            if (!FF) tp--;
                    }
                    
            if (FF2) {
                        tp 
            = 0; vst0[y0] = 1while (x0 != y0) {stk[tp++= x0; vst0[x0] = 1; x0 = E0[pr[x0]].a;} stk[tp++= y0;
                        re(j, tp) sol0(stk[j]);
                        tmp0 
            = F[stk[0]][0]; tmp1 = -INF;
                        re2(j, 
            1, tp) {
                            tmp00 
            = (tmp0 >= tmp1 ? tmp0 : tmp1) + F[stk[j]][0];
                            tmp01 
            = tmp0 + F[stk[j]][1];
                            tmp0 
            = tmp00; tmp1 = tmp01;
                        }
                        res0 
            = tmp0 >= tmp1 ? tmp0 : tmp1;
                        tmp0 
            = -INF; tmp1 = F[stk[0]][1];
                        re2(j, 
            1, tp) {
                            tmp00 
            = (tmp0 >= tmp1 ? tmp0 : tmp1) + F[stk[j]][0];
                            tmp01 
            = tmp0 + F[stk[j]][1];
                            tmp0 
            = tmp00; tmp1 = tmp01;
                        }
                        res 
            += res0 >= tmp0 ? res0 : tmp0;
                    }
                }
            }
            void pri()
            {
                cout 
            << res << endl;
            }
            int main()
            {
                init();
                solve();
                pri();
                
            return 0;
            }


            久久久久亚洲av成人网人人软件| 97久久综合精品久久久综合| 欧洲国产伦久久久久久久| 美女久久久久久| 人妻无码αv中文字幕久久| 国产精品一区二区久久| A狠狠久久蜜臀婷色中文网| 久久99精品久久久久久水蜜桃 | 久久精品国产亚洲av水果派| 久久青青草原综合伊人| 久久久久人妻精品一区三寸蜜桃| 亚洲国产成人久久综合区| 久久影视综合亚洲| 国产综合久久久久| 久久久久久久97| 天天久久狠狠色综合| 影音先锋女人AV鲁色资源网久久| 国内精品久久久久国产盗摄| 无码人妻久久一区二区三区蜜桃| 国产91色综合久久免费分享| 国産精品久久久久久久| 国产综合久久久久| 久久国产欧美日韩精品| 久久人人爽人人爽AV片| 99久久精品无码一区二区毛片| 无码人妻久久一区二区三区免费丨 | 99久久亚洲综合精品网站| 一级做a爰片久久毛片免费陪| 久久人人爽人人爽人人片AV麻豆| 色综合久久88色综合天天 | 四虎影视久久久免费| 久久青青草原综合伊人| 狠狠干狠狠久久| 久久99国产精品二区不卡| 久久国产精品99精品国产| 久久精品99久久香蕉国产色戒 | 久久精品国产免费观看三人同眠| 久久久人妻精品无码一区| 国产精品日韩欧美久久综合| 国产精品久久久久久一区二区三区| 久久香蕉综合色一综合色88|