• <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
            終于AK了,作為題解寫在這里,我的ID: hanfei19910905

            A
            簡單的字符串處理(略)

            B
            有N張撲克牌(N<=52)排成一行,四種花色12種點數。每次可以將最右一堆牌(位置k)至于k-1或者k-3的頂部,當且僅當花色或者點數相等。問最后是否可以合并為一堆。
            算法分析:
                動態規劃,DP[i,a,b,c]代表長度為i,最后三堆頂部為a,b,c,是否可以合并為一堆。
                轉移: dp[i,a,b,c] = dp[i-1,c,a,b] | dp[i-1,num[i-3],a,c]。

            #include<iostream>
            #include<cstring>
            #include<string>
            #include<cstdio>
            using namespace std;
            const string aa = "23456789TJQKA";
            const string bb = "SDHC";
            string ch[100];
            int num[100];
            int dp[60][60][60][60];
            bool chk(int a,int b){
                return a/13 == b/13 || a % 13 == b%13;
            }
            bool dfs(int p,int a,int b,int c){
                int &ans = dp[p][a][b][c];
                if(ans !=-1) return ans;
                if(p == 0) return chk(b,c) && chk(a,c);
                ans = 0;
                if(chk(c,b)) ans = dfs(p-1,num[p-1],a,c);
                if(chk(num[p-1],c)) ans |= dfs(p-1,c,a,b);
                return ans;
            }
            int find(const string& a, char b){
                for(int i=0;i<a.size();i++)
                    if(b==a[i]) return i;

            }
            int main(){
                int n;
                while(cin >> n){
                    for(int i=0;i<n;i++){
                        cin >> ch[i];
                        num[i] = find(bb,ch[i][1]) * 13 + find(aa,ch[i][0]);
                    }
                    memset(dp,-1,sizeof(dp));
                    if(n == 1) puts("YES");
                    if(n == 2) puts(chk(num[0],num[1]) ? "YES" : "NO");
                    if(n >= 3) puts(dfs(n-3,num[n-3],num[n-2],num[n-1]) ? "YES" : "NO");
                }
            }
            C
            有點數為N(N<=100)的無向圖。現在要選擇一個點,給這個點的鄰接邊染色。讓1到n的所有最短路經過的染色邊的期望最高,求最高期望。
            算法分析:
                設f(s,e)是s到e有多少條最短路,廣搜可求。復雜度O(V+E)
                先將1到n有多少條最短路求出來。
                然后枚舉每個點u,如果這是最短路上的點,那么選擇它的期望是 2*f(1,u)*f(u,n)/f(1,n)。
                復雜度O(V*(V+E))

            #include<iostream>
            #include<cstdio>
            using namespace std;
            const int V = 105;
            int G[V][V],dis[V][V]; double dp[V];
            int Q[V], stp[V],Du[V]; double way[V];
            int n,m;
            template <typename T>inline void chkmax(T &a, const T b){if(a<b) a= b;}
            void bfs(int s,int e){
                for(int i=0;i<n;i++){
                    stp[i] = -1;
                    way[i] = 0;
                }
                way[s] = 1.0;
                stp[s] = 0;
                Q[0] = s;
                int head = 0, tail = 1;
                while(head<tail){
                    int u= Q[head++];
                    for(int v = 0; v<n; v++) if(G[u][v]){
                        if(stp[v] == -1){
                            stp[v] = stp[u] + 1;
                            way[v] = way[u];
                            Q[tail ++] = v;
                            if(v == e) Du[v] = 1;
                        }
                        else if(stp[v] == stp[u] + 1){
                            way[v] += way[u];
                            if(v == e) Du[v] ++;
                        }
                    }
                }
                dis[s][e] = dis[e][s] = stp[e];
                dp[e] *= way[e];
            }
            int main(){
                while(~scanf("%d%d",&n,&m)){
                    for(int i=0;i<n;i++)
                        for(int j=0;j<n;j++)
                            G[i][j] = 0;
                    for(int i=0;i<n;i++) Du[i] = 0, dp[i] = 1.0;
                    for(int i=0;i<m;i++){
                        int u,v;
                        scanf("%d%d",&u,&v);
                        u--; v--;
                        G[u][v] = G[v][u] = 1;
                    }
                    bfs(0,n-1);
                    bfs(n-1,0);
                    double ans =1.0; 
                    for(int i=1;i<n-1;i++){
                        bfs(0,i);
                        bfs(n-1,i);
                        if(dis[0][i] + dis[i][n-1] == dis[0][n-1])
                            chkmax(ans, 2* dp[i]/dp[0] );
                    }
                    printf("%.10lf\n",ans);
                }
            }
            D
            簡單貪心(略)
            E
            給一個森林,點數為100,000。詢問100,000次。每次給點u,整數數k。問有多少個點v,是u的第k個祖先的孩子,且距離還是k。
            算法分析:
                
                預處理出u的2^i個祖先。再把同一深度的點放到一個vector里。
                設u的k祖先是v。在深度為k+deep[v]的vector里,找第一時間戳位于v的第一時間戳和第二時間戳的之間的所有點。二分可解。
                預處理O(nlogn)詢問log(n)
            #include<iostream>
            #include<cstdio>
            #include<vector>
            using namespace std;
            const int MXB = 18;
            const int V = 100005;
            const int E = V<<1;
            // build graph
            int head[V], nxt[E], pnt[E], e;
            void add(int u,int v){
                nxt[e] = head[u];
                head[u] = e;
                pnt[e++] = v;
            }
            // dfs
            int dep[V],tm,pre[V],snd[V],P[V][MXB];
            vector<int> temp[V];
            void dfs(int u,int f){
                dep[u] = dep[f] + 1;
                temp[dep[u]].push_back(tm);
                pre[u] = tm++;
                P[u][0] = f;
                for(int i=1; i< MXB; i++){
                    P[u][i] = P[P[u][i-1]][i-1];
                }
                for(int i=head[u];i!=-1;i=nxt[i]){
                    int v = pnt[i];
                    if(v == f) continue;
                    if(pre[v]==-1) dfs(v,u);
                }
                snd[u] = tm++;
            }
            // lca
            inline void goup(int &u,int d){
                for(int i=0;i<MXB;i++) if((1<<i) & d)
                    u = P[u][i];
            }
            int find(int v,int k){
                vector<int> &t = temp[k];
                int l =0, r = t.size();
                while(l<r){
                    int mid = l+r >>1;
                    if(t[mid] >= v) r = mid; else l = mid+1;
                }
                return r;
            }
            // main
            int main(){
                int n;
                cin >> n;
                static int prt[V] ;
                for(int i=1;i<=n;i++) pre[i] = head[i] = -1;
                tm = e = 0;
                for(int i=1;i<=n;i++){
                    scanf("%d",&prt[i]);
                    if(prt[i]) {add(i,prt[i]); add(prt[i],i);}
                }
                forint i=1; i<=n ; i++) if(!prt[i]) dfs(i, 0);
                int q,u,k; cin >> q;
                while(q -- ){
                    scanf("%d%d",&u,&k);
                    goup(u,k);
                    if(!u) {cout<<"0 "; continue;}
                    k += dep[u];
                    cout<< find(snd[u],k) - find(pre[u],k) - 1 <<" ";
                }
                cout<< endl;
            }
            posted on 2012-07-24 17:23 西月弦 閱讀(304) 評論(2)  編輯 收藏 引用 所屬分類: 解題報告

            FeedBack:
            # re: codeforces #130 div2
            2012-07-25 19:29 | wuyiqi
            最后一題你找LCA用的是什么方法?好簡潔  回復  更多評論
              
            # re: codeforces #130 div2
            2012-07-25 19:30 | 西月弦
            @wuyiqi
            倍增法  回復  更多評論
              
            久久影院亚洲一区| 99久久99这里只有免费费精品| 国产午夜福利精品久久2021 | 久久精品国产亚洲av水果派| 国产成人久久精品一区二区三区| 99久久精品免费看国产免费| 日本精品久久久久影院日本| 国产麻豆精品久久一二三| 久久se精品一区精品二区国产| 老男人久久青草av高清| 青青草原精品99久久精品66| AA级片免费看视频久久| 成人久久免费网站| 久久国产成人午夜aⅴ影院 | AV色综合久久天堂AV色综合在 | 久久久久久午夜成人影院 | 亚洲精品国产自在久久| 久久99精品国产一区二区三区| 久久久久久国产精品无码下载 | 日本精品久久久久影院日本| 国产一区二区精品久久 | 久久av无码专区亚洲av桃花岛| 天天影视色香欲综合久久| 久久精品成人免费看| 亚洲AV无码一区东京热久久| 久久精品国产精品亚洲| 精品国产一区二区三区久久| 伊人久久精品无码av一区| 久久亚洲国产精品五月天婷| 九九热久久免费视频| 国产精品美女久久久久网| 久久婷婷国产综合精品| 久久精品国产亚洲av水果派 | 精品久久久久久国产免费了| 色综合久久88色综合天天 | 久久久久亚洲Av无码专| 狠狠色丁香久久婷婷综合_中 | 久久无码一区二区三区少妇| 久久男人AV资源网站| 色婷婷噜噜久久国产精品12p| 一本色道久久综合狠狠躁篇|