• <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年7月>
            2829301234
            567891011
            12131415161718
            19202122232425
            2627282930311
            2345678

            "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

            搜索

            •  

            最新評論

            評論排行榜

            国产精品一区二区久久国产| 国产精品青草久久久久福利99| 久久综合伊人77777麻豆| 精品国产乱码久久久久久浪潮| 久久综合亚洲欧美成人| 亚洲国产精品无码久久一线| 久久精品国产清高在天天线| 99久久www免费人成精品| 国产69精品久久久久APP下载| 狠狠88综合久久久久综合网| 狠狠久久综合| 久久无码人妻一区二区三区 | 国产真实乱对白精彩久久| 欧美午夜A∨大片久久 | 久久久国产打桩机| 久久w5ww成w人免费| 青青久久精品国产免费看| 97r久久精品国产99国产精| 亚洲精品tv久久久久久久久久| 国产亚洲精久久久久久无码AV| 色狠狠久久AV五月综合| 伊人久久大香线蕉影院95| 欧洲成人午夜精品无码区久久| 国产精品中文久久久久久久| 国产巨作麻豆欧美亚洲综合久久 | 久久噜噜电影你懂的| 久久综合九色欧美综合狠狠| 久久免费小视频| 久久精品人人做人人爽97| 日本强好片久久久久久AAA| 伊人久久无码精品中文字幕| 久久久久亚洲爆乳少妇无| 国产视频久久| 亚洲午夜久久久| 色婷婷噜噜久久国产精品12p| 久久se精品一区二区影院| 女人香蕉久久**毛片精品| 久久久久久久综合日本亚洲| 日韩一区二区久久久久久| 国产精品伦理久久久久久| 久久精品国产精品亚洲艾草网美妙|