• <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 閱讀(1061) 評論(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;
            }


            色偷偷888欧美精品久久久| 久久午夜免费视频| 日本免费久久久久久久网站| 国产成人精品久久亚洲高清不卡 | 激情久久久久久久久久| 色偷偷91久久综合噜噜噜噜| 国产99久久久国产精品小说| 色狠狠久久AV五月综合| 国产高清国内精品福利99久久| 欧美激情精品久久久久久久九九九| 久久影院综合精品| 久久免费99精品国产自在现线 | 亚洲va中文字幕无码久久不卡| 久久亚洲日韩精品一区二区三区| 精品国产综合区久久久久久| 国产成人无码精品久久久性色 | 综合久久一区二区三区 | 久久久久久国产精品美女| 久久er国产精品免费观看2| 久久综合亚洲色HEZYO社区| 人人狠狠综合久久亚洲婷婷| 精品久久久无码人妻中文字幕| 国产99久久久国产精品~~牛| 亚洲精品无码久久久久去q| 久久影视综合亚洲| 亚洲综合久久综合激情久久| 精品永久久福利一区二区| 久久久久亚洲精品日久生情| 国产巨作麻豆欧美亚洲综合久久| 久久久久久久久久久久中文字幕| 久久亚洲中文字幕精品一区| 青青青青久久精品国产h久久精品五福影院1421 | 国产精品对白刺激久久久| 狠狠色丁香久久婷婷综合| 欧美色综合久久久久久| 久久久中文字幕日本| 久久国产V一级毛多内射| 国产三级观看久久| 久久精品综合一区二区三区| 亚洲国产成人久久精品动漫| 91久久精品电影|