• <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 - 43,  comments - 9,  trackbacks - 0

            題目給出一棵樹(N<=10000)以及所有邊的權(<=10000). 現在要求對任意查詢Q(<=10^8), 判斷是否存在一條邊權之和恰好為Q的路徑.
            標程的方法暫時沒看懂= =... 
            我用樹的分治做(更多相關內容見09國家集訓隊漆子超的論文)
            考慮一棵以root為根的子樹, 那么在這棵子樹中, 有多少條 v1->root->v2 的路徑長恰好為Q呢? 可以先DFS一次子樹, 求出所有點到root的距離, 將這些距離排個序,  就能在klogk的時間里求出滿足和為Q的組合數count[root,Q]. 但是這樣把路徑重疊, 也就是v1->v'->root->v'->v2的情況也算進去了.  考慮不合法的狀態, 如果有邊重復, 那么其中肯定包含root到某個兒子的邊, 也就是形如v1->chi->root->chi->v2. 所以count[root,Q]中不合法路徑數為sigma(count[chi,Q-2*dist[root][chi]]), 求出來減去即可.
            這樣處理完以root為根的樹后, 結點root已經沒有用了. 也就是說剩下的只須處理它的所有兒子樹,  轉化為新的獨立問題.
            這樣不斷地處理樹, 將樹分成新子樹, 最后完成所有子樹的統計.

            恰當選擇每次拆分的樹根可以使復雜度變成nlogn, 否則總復雜度仍然是n^2. 一個較方便的規則是: 選擇樹的平衡點, 也就是拿掉這個點后形成的森林里, max(|tree[i]|)最小.
            這樣的點可以對樹DFS一次做DP求得. pku1655就是解決這個問題.

            ps.pku1741與此題幾乎完全一樣, 唯一不同的是那題是求dist<=Q的路徑的數量.

            代碼:

              1#include <iostream>
              2#include <algorithm>
              3using namespace std;
              4
              5//#define DEBUG
              6
              7const int MAX_V = 11000;
              8const int MAX_E = MAX_V*5;
              9
             10struct EDGE{
             11  int v,e,w;
             12}
            edg[MAX_E];
             13int se, gg[MAX_V];
             14bool ok[MAX_E];
             15int vis[MAX_V], stamp;
             16int que[MAX_V*5], sque, pque;
             17int card[MAX_V], chm[MAX_V], sum[MAX_V], det[MAX_V];
             18int gdd[MAX_V],sdd;
             19int ans;
             20int N,L; 
             21
             22void addedge(int u, int v, int w)
             23{
             24  edg[se].v=v; edg[se].w=w; edg[se].e=gg[u]; gg[u]=se++;
             25  edg[se].v=u; edg[se].w=w; edg[se].e=gg[v]; gg[v]=se++;
             26}

             27
             28void dfsplus(int rt, int ss, int di, int &idx, int &cnt) 
             29{
             30  //求距離的同時找重心
             31  vis[rt]=stamp;
             32  chm[rt]=0, card[rt]=1;
             33  gdd[sdd++]=di;
             34  for(int j=gg[rt]; j>0; j=edg[j].e){
             35    if(ok[j])continue;
             36    int v=edg[j].v;
             37    if(vis[v]==stamp)continue;
             38    dfsplus(v, ss, di+edg[j].w, idx, cnt);
             39    card[rt]+=card[v];
             40    chm[rt]=max(chm[rt],card[v]);
             41  }

             42  chm[rt]=max(chm[rt],ss-card[rt]);
             43  if(chm[rt]<cnt)
             44    idx=rt, cnt=chm[rt];
             45}

             46
             47int matchdist(int d)
             48{
             49  int ret=0;
             50  sort(gdd,gdd+sdd);
             51  int q1=0, q2=sdd-1;
             52  //線性的掃描求組合數, 可惜前面的排序多了個logn
             53  while(q1<=q2){
             54    if(gdd[q1]+gdd[q2]<d)q1++;
             55    else if(gdd[q1]+gdd[q2]>d)q2--;
             56    else{
             57      if(gdd[q1]==gdd[q2]){
             58        ret+=(q2-q1)*(q2-q1+1)/2
             59        break;
             60      }

             61      else{
             62        int p1=q1+1, p2=q2-1;
             63        while(p1<sdd && gdd[p1]==gdd[q1]) p1++;
             64        while(p2>=0 && gdd[p2]==gdd[q2]) p2--;
             65        ret+=(p1-q1)*(q2-p2);
             66        q1=p1, q2=p2;
             67      }

             68    }

             69  }

             70  return ret;
             71}

             72
             73void solve()
             74{
             75  int i,j,k;  
             76  pque=sque=0;
             77  ans=0;
             78  stamp=0;
             79  memset(vis,0,sizeof(vis));
             80  det[1]=-1; sum[1]=N;
             81  que[sque++]=1;
             82  while(pque!=sque){
             83    int u=que[pque++];
             84    int idx=u, cnt=N+1;
             85    sdd=0;
             86    ++stamp;
             87    dfsplus(u, sum[u], 0, idx, cnt);
             88    if(det[u]>0 && L-det[u]*2>=0){
             89      //減去它父親的非法路徑數
             90      ans-=matchdist(L-det[u]*2);
             91    }

             92    u=idx;
             93    sdd=0;
             94    ++stamp;
             95    dfsplus(u, sum[u], 0, idx, cnt);
             96    //加上自己的總路徑數
             97    ans+=matchdist(L);
             98    for(j=gg[u]; j>0; j=edg[j].e){
             99      if(ok[j])continue;
            100      int v=edg[j].v;
            101      det[v]=edg[j].w;
            102      ok[j^1]=true//切斷子樹和父親的邊
            103      sum[v]=card[v];
            104      que[sque++]=v;
            105    }

            106  }

            107  if(ans>0) puts("AYE");
            108  else puts("NAY");
            109}

            110
            111int main()
            112{
            113  int i,j,k,u,v,w;
            114  while(true){
            115    scanf("%d",&N);
            116    if(N==0)break;
            117    se=2;
            118    memset(gg,0,sizeof(gg));
            119    for(u=1; u<=N; u++){
            120      while(true){
            121        scanf("%d",&v);
            122        if(v==0)break;
            123        scanf("%d",&w);
            124        addedge(u,v,w);
            125      }

            126    }

            127    while(true){
            128      scanf("%d",&L);
            129      if(L==0)break;
            130      memset(ok,false,sizeof(ok));
            131      solve();
            132    }

            133    printf(".\n");
            134  }

            135}

            136
            posted on 2009-07-31 14:30 wolf5x 閱讀(499) 評論(0)  編輯 收藏 引用 所屬分類: acm_icpc
            <2009年3月>
            22232425262728
            1234567
            891011121314
            15161718192021
            22232425262728
            2930311234

            "Do not spend all your time on training or studying - this way you will probably become very exhausted and unwilling to compete more. Whatever you do - have fun. Once you find programming is no fun anymore – drop it. Play soccer, find a girlfriend, study something not related to programming, just live a life - programming contests are only programming contests, and nothing more. Don't let them become your life - for your life is much more interesting and colorful." -- Petr

            留言簿(3)

            隨筆分類(59)

            隨筆檔案(43)

            cows

            搜索

            •  

            最新評論

            評論排行榜

            狠狠色综合网站久久久久久久高清| 久久精品国产亚洲AV麻豆网站| 青青青国产精品国产精品久久久久 | 精品无码久久久久久尤物| 久久国产乱子伦免费精品| 精品久久久久久久| 无码精品久久一区二区三区| 亚洲中文字幕无码久久2020| 久久婷婷综合中文字幕| 狠狠色丁香久久婷婷综合蜜芽五月| 人妻久久久一区二区三区| 狠狠色婷婷综合天天久久丁香| 久久青青草原精品国产软件| 香蕉久久夜色精品升级完成| 久久久久人妻一区精品果冻| 国内精品久久久久久99蜜桃| 亚洲国产成人久久一区久久| 77777亚洲午夜久久多喷| 色悠久久久久久久综合网| www.久久热.com| 亚洲日韩中文无码久久| 久久中文字幕视频、最近更新| 久久天天躁狠狠躁夜夜avapp| 婷婷久久综合| 国产一区二区精品久久凹凸| 久久国产精品无码一区二区三区 | 久久久久亚洲AV成人网人人网站| 亚洲AV无码久久寂寞少妇| 亚洲Av无码国产情品久久| 69久久精品无码一区二区| 久久精品人人做人人爽电影| 久久精品夜色噜噜亚洲A∨| 人人狠狠综合久久亚洲婷婷| 97精品久久天干天天天按摩| 无码国内精品久久人妻| 精品伊人久久大线蕉色首页| 久久天天躁狠狠躁夜夜2020一| 亚洲欧美一级久久精品| 久久亚洲中文字幕精品一区四| 99久久精品无码一区二区毛片 | 久久九九亚洲精品|