青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

糯米

TI DaVinci, gstreamer, ffmpeg
隨筆 - 167, 文章 - 0, 評論 - 47, 引用 - 0
數據加載中……

POJ 1987 Distance Statistics 牛題 樹的分治

這題很牛逼,是樓教主的《男人七題》的其中一道。
求:一棵樹內最短距離小于K的點對數量
后來看了解題報告,原來樹也是可以分治的。

分:
選取一條邊,將一棵樹分成兩半,這兩半的節點數要盡量相等。
首先,統計個每個節點的下面有多少個節點
然后,就知道每個邊切斷之后的情況了。選擇最優的即可。

治:
分成兩半之后,統計經過該條邊的點對線段中,長度小于K的數目。

Amber 大牛論文的精辟描述如下:
 

Divide and Conquer.

Each iteration, we should choose an edge (u, v) and divide the tree into two parts disjoined by the edge. Due to avoid from degenerating, that partition edge should be chosen to divide two parts as equally as possible. Then we should merge two parts and count the valid pairs between them. It can be implemented by two sorted list that denotes the distances between u and the posterities of u and the distances between u and the posterities of v respectively. And like merge sort, use two scan line l, r in two list and maintain the property d(u, l) + d(v, r) <= k.


可見這位大牛的英文水平實在牛逼,英文說得比中文說得還清楚,贊一個。

按照這個思路,很費勁地寫出了代碼。還好,在1987上面還是勉強上榜啦!250ms那個就是我啦,哈哈。
但是在樓教主的題目1741 上面還是 TLE了。

后來找了一份能過1741的代碼,在http://hi.baidu.com/shingray/blog/item/221362b079afc55d082302f0.html
一個大牛的博客上~
發現它的思路不是選擇一條邊來把樹分成兩份。
而是選擇一個點來把樹分成數份,然后計算經過該點的線段數目。
這樣速度就快了,大牛的代碼在1741上面只跑了170多ms。
將這份代碼放到1987上面,也能跑到260ms。
所以這種方法還是很牛逼的!


我的垃圾代碼(POJ 1987):
#include <stdio.h>
#include 
<stdlib.h>

#define MAX_VETXS 65536*2
#define MAX_EDGES (MAX_VETXS - 1)

#if 0
#define dbp printf
#else
#define dbp()
#endif

struct edge_node {
    
int w, i;
    
struct edge_node *next, *prev;
}
;

struct edge_node edges[MAX_EDGES], map[MAX_VETXS];
int edges_cnt;
int N, K, ans;

int cmp(const void *a, const void *b)
{
    
return *(int *)a - *(int *)b;
}


inline 
int max(int a, int b)
{
    
return a > b ? a : b;
}


#define list_foreach(_head, _t)    \
    
for (_t = (_head)->next; _t != _head; _t = (_t)->next)

inline 
void list_init(struct edge_node *t)
{
    t
->next = t->prev = t;
}


inline 
void list_add(struct edge_node *head, struct edge_node *t)
{
    head
->prev->next = t;
    t
->prev = head->prev;
    head
->prev = t;
    t
->next = head;
}


inline 
void list_del(struct edge_node *t)
{
    t
->prev->next = t->next;
    t
->next->prev = t->prev;
}


inline 
void list_rev(struct edge_node *t)
{
    t
->next->prev = t;
    t
->prev->next = t;
}


inline 
void edge_add(int a, int b, int w)
{
    
struct edge_node *= &edges[edges_cnt++];

    t
->= b;
    t
->= w;
    list_add(
&map[a], t);
}


struct part_info {
    
int u, v, e, cnt_v;
}
;

inline 
void divide(int i, int *arr, int *len, int cnt, struct part_info *pi)
{
    
static struct {
        
int i, e, depth, cnt, stat, root;
    }
 stk[MAX_VETXS], *sp, *top;
    
static int vis[MAX_VETXS], tm, best, val;
    
int *orig = arr;
    
struct edge_node *e;
    
    best 
= cnt;
    tm
++;
    top 
= stk + 1;
    top
->= i;
    top
->depth = top->cnt = top->stat = top->root = 0;
    vis[i] 
= tm;
    
while (top > stk) {
        sp 
= top;
        
if (sp->stat) {
            stk[sp
->root].cnt += sp->cnt;
            
if (arr && sp->depth <= K)
                
*arr++ = sp->depth;
            val 
= max(sp->cnt, cnt - sp->cnt);
            
if (val < best) {
                best 
= val;
                pi
->= stk[sp->root].i;
                pi
->= sp->i;
                pi
->= sp->e;
                pi
->cnt_v = sp->cnt;
            }

            top
--;
            
continue;
        }

        sp
->stat++;
        list_foreach(
&map[sp->i], e) {
            
if (vis[e->i] == tm)
                
continue;
            vis[e
->i] = tm;
            top
++;
            top
->= e->i;
            top
->= e - edges;
            top
->depth = sp->depth + e->w;
            top
->cnt = 1;
            top
->stat = 0;
            top
->root = sp - stk;
        }

    }


    
if (len)
        
*len = arr - orig;
}


void conquer(struct part_info *pi, int cnt)
{
    
struct part_info pl, pr;
    
static int arr_l[MAX_VETXS], arr_r[MAX_VETXS], len_l, len_r, l, r;

    
if (cnt <= 1)
        
return ;

    list_del(
&edges[pi->e]);
    list_del(
&edges[pi->^ 1]);
    
    divide(pi
->u, arr_l, &len_l, cnt - pi->cnt_v, &pl);
    divide(pi
->v, arr_r, &len_r, pi->cnt_v, &pr);
    
    qsort(arr_l, len_l, 
sizeof(arr_l[0]), cmp);
    qsort(arr_r, len_r, 
sizeof(arr_r[0]), cmp);

    r 
= len_r - 1;
    
for (l = 0; l < len_l; l++{
        
while (r >= 0 && arr_l[l] + arr_r[r] + edges[pi->e].w > K)
            r
--;
        ans 
+= r + 1;
    }

    
    conquer(
&pl, cnt - pi->cnt_v);
    conquer(
&pr, pi->cnt_v);
    
    list_rev(
&edges[pi->e]);
    list_rev(
&edges[pi->^ 1]);
}


inline 
void solve_v2()
{
    
struct part_info pi;

    divide(
1, NULL, NULL, N, &pi);
    conquer(
&pi, N);
}


int main()
{
    
int i, a, b, w, m;
    
char str[16];

    freopen(
"e:\\test\\in.txt""r", stdin);

    scanf(
"%d%d"&N, &m);
    edges_cnt 
= 0;
    
for (i = 1; i <= N; i++)
        list_init(
&map[i]);
    
for (i = 0; i < m; i++{
        scanf(
"%d%d%d%s"&a, &b, &w, str);
        edge_add(a, b, w);
        edge_add(b, a, w);
    }

    scanf(
"%d"&K);
    ans 
= 0;
    solve_v2();
    printf(
"%d\n", ans);

    
return 0;
}



大牛的代碼(POJ 1987):
#include <algorithm>
#include 
<cstdio>
#include 
<cstring>
#include 
<limits>
#include 
<queue>
#include 
<vector>
using namespace std;

const int MAX_N = 65536*2;
bool flag[MAX_N];
int k, n, ret, v[MAX_N];
queue
<pair<intint> > q;

struct edge{int v, w; edge *next; } *e[MAX_N], data[MAX_N*2-2], *it;
void insert(int u, int v, int w)
{
   
*it = (edge){v, w, e[u]}; e[u] = it++;
   
*it = (edge){u, w, e[v]}; e[v] = it++;
}


int count(int *first, int *last)
{
   
int ret = 0;
   sort(first, last
--);
   
while (first < last)
       
if (*first+*last <= k) ret += last-first++;
       
else --last;
   
return ret;
}


int best_size, center;
int centerOfGravity(int root, int pred)
{
   
int max_sub = 0, size = 1;
   
for (edge *it = e[root]; it; it = it->next)
       
if (it->!= pred && flag[it->v])
       
{
           
int t = centerOfGravity(it->v, root);
           size 
+= t;
           
if (t > max_sub) max_sub = t;
       }

   
if (q.front().second-q.front().first-max_sub > max_sub)
       max_sub 
= q.front().second-q.front().first-max_sub;
   
if (max_sub < best_size)
       best_size 
= max_sub, center = root;
   
return size;
}


int dists[MAX_N], len;
void find(int root, int pred, int dist)
{
   v[len] 
= root;
   dists[len
++= dist;
   
int last = len;
   
for (edge *it = e[root]; it; it = it->next)
       
if (it->!= pred && flag[it->v])
       
{
           find(it
->v, root, dist+it->w);
           
if (pred == -1)
           
{
               q.push(make_pair(last, len));
               ret 
-= count(dists+last, dists+len);
               last 
= len;
           }

       }

}


int main()
{
    
int m;
    
char str[16];
   scanf(
"%d%d"&n, &m);
   
{
       it 
= data;
       memset(e, 
0sizeof(e[0])*n);
       
for (int i = n; --i; )
       
{
           
int u, v, w;
           scanf(
"%d%d%d%s"&u, &v, &w, str);
           
--u; --v;
           insert(u, v, w);
       }

       scanf(
"%d"&k);

       ret 
= 0;
       
for (int i = 0; i < n; ++i)
           v[i] 
= i;
       
for (q.push(make_pair(0, n)); !q.empty(); q.pop())
       
{
           
if (q.front().first == q.front().second-1continue;
           
for (int i = q.front().first; i < q.front().second; ++i)
               flag[v[i]] 
= true;

           best_size 
= numeric_limits<int>::max();
           centerOfGravity(v[q.front().first], 
-1);

           len 
= q.front().first;
           find(center, 
-10);
           ret 
+= count(dists+q.front().first, dists+q.front().second);

           
for (int i = q.front().first; i < q.front().second; ++i)
               flag[v[i]] 
= false;
       }

       printf(
"%d\n", ret);
   }

}

posted on 2010-04-25 22:30 糯米 閱讀(760) 評論(0)  編輯 收藏 引用 所屬分類: POJ

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            在线视频欧美精品| 尤物视频一区二区| 国产精品视频免费在线观看| 国产精品一区二区欧美| 在线看片日韩| 国产日韩欧美夫妻视频在线观看| 一区在线观看| 欧美在线啊v| 亚洲七七久久综合桃花剧情介绍| 亚洲午夜激情在线| 美女任你摸久久| 国产九区一区在线| 日韩香蕉视频| 欧美高清在线| 久久亚洲精品欧美| 亚洲一区在线观看视频 | 久久久久久久综合色一本| 欧美日韩在线直播| 91久久精品一区| 久久天天躁狠狠躁夜夜av| 亚洲丝袜av一区| 麻豆成人在线| 亚洲欧美日韩精品久久久久| 久久精品欧美日韩精品| 国产精品欧美久久| 99精品免费| 亚洲福利av| 午夜伦欧美伦电影理论片| 理论片一区二区在线| 国内精品久久久久影院薰衣草| 亚洲婷婷在线| 99国产成+人+综合+亚洲欧美| 免费在线成人| 亚洲韩国精品一区| 欧美大胆人体视频| 久久一区二区三区av| 樱花yy私人影院亚洲| 蜜桃av噜噜一区| 久久精品91久久香蕉加勒比| 国内精品久久久久伊人av| 久久精品卡一| 久久国产一区| 国产美女扒开尿口久久久| 一本久道久久久| 亚洲美女中文字幕| 欧美日韩一区二区三区免费| 一本一本久久a久久精品综合麻豆 一本一本久久a久久精品牛牛影视 | 欧美另类69精品久久久久9999| 亚洲高清在线视频| 欧美高潮视频| 欧美极品在线视频| 在线日韩一区二区| 最新日韩中文字幕| 欧美视频在线一区二区三区| 欧美一区二区在线免费观看| 久久精品卡一| 亚洲乱码久久| 亚洲午夜女主播在线直播| 国产日韩专区| 欧美韩日一区| 国产精品二区二区三区| 久久激情视频| 欧美mv日韩mv国产网站app| 洋洋av久久久久久久一区| 亚洲网在线观看| 亚洲国产精品www| 一本色道久久加勒比精品| 国产综合av| 日韩一本二本av| 一区二区在线视频观看| 亚洲精品视频免费在线观看| 国产欧美亚洲一区| 欧美资源在线观看| 欧美成人中文| 午夜精品久久久久99热蜜桃导演| 欧美中文字幕精品| 一区二区三区精品| 性久久久久久久久久久久| 亚洲精品乱码久久久久久按摩观| 亚洲欧美网站| 免费91麻豆精品国产自产在线观看| 一区二区黄色| 久久久美女艺术照精彩视频福利播放| 亚洲精品一二区| 欧美一区二区三区四区高清 | 一区二区日韩免费看| 国产亚洲免费的视频看| 亚洲精品少妇| 曰韩精品一区二区| 亚洲一区日韩在线| 日韩小视频在线观看| 久久国产精品高清| 亚洲免费一级电影| 欧美色大人视频| 一本色道久久综合亚洲精品按摩| 99精品久久久| 欧美婷婷久久| 在线亚洲国产精品网站| 亚洲欧美国产精品va在线观看| 欧美午夜电影网| 亚洲色无码播放| 欧美中文日韩| 国内视频一区| 蜜臀久久99精品久久久久久9| 欧美激情1区2区| 亚洲精品美女| 欧美午夜激情视频| 亚洲免费视频中文字幕| 久久xxxx| 亚洲第一区中文99精品| 欧美电影在线观看| 一本一本a久久| 欧美中文字幕精品| 亚洲电影中文字幕| 欧美日韩国产精品| 亚洲自拍三区| 裸体素人女欧美日韩| 99re热精品| 国产欧美日韩视频一区二区| 久久午夜国产精品| 亚洲欧洲综合| 午夜精品福利一区二区蜜股av| 国产午夜亚洲精品不卡| 久久一区二区视频| 欧美激情影院| 午夜国产精品影院在线观看 | 伊人精品在线| 欧美激情一区二区三区成人| 亚洲午夜精品| 免费人成精品欧美精品| 一区二区三区**美女毛片| 国产精品主播| 欧美成人中文| 欧美一区观看| 亚洲毛片在线看| 美女脱光内衣内裤视频久久网站| 99综合视频| 伊人春色精品| 国产精品电影观看| 欧美a级理论片| 欧美一级大片在线免费观看| 最新国产成人av网站网址麻豆| 欧美在线观看网址综合| 日韩午夜免费| 伊人久久亚洲美女图片| 久久精品视频va| 99国产精品99久久久久久粉嫩| 久久亚洲捆绑美女| 亚洲天天影视| 亚洲精品欧美在线| 狠狠色狠狠色综合| 国产精品一国产精品k频道56| 欧美成人精品在线观看| 欧美在线观看视频| 亚洲一区二区在线| 亚洲美女精品久久| 欧美护士18xxxxhd| 久久免费国产| 久久爱www久久做| 亚洲精品久久| 蜜臀av在线播放一区二区三区| 亚洲欧美制服中文字幕| 宅男精品导航| 亚洲精品日韩久久| 一区二区三区在线观看国产| 国产欧美精品久久| 国产精品麻豆成人av电影艾秋| 欧美日本一区二区三区| 欧美成人午夜视频| 老司机精品视频网站| 久久精品一区二区| 久久爱www.| 久久福利影视| 久久精品在这里| 久久久精品999| 久久精品一二三| 久久九九免费| 久久综合久久综合久久综合| 久久久久国内| 久久天天躁狠狠躁夜夜爽蜜月| 久久国产手机看片| 久久精品国产v日韩v亚洲| 久久国产色av| 葵司免费一区二区三区四区五区| 久久久久久久精| 麻豆成人精品| 欧美jjzz| 欧美日韩一区二区三区在线观看免| 欧美欧美午夜aⅴ在线观看| 欧美极品在线视频| 欧美三区不卡| 国产欧美日韩伦理| 一区二区三区在线看| 亚洲激情视频网站| 日韩视频精品在线| 亚洲少妇诱惑| 久久国产99| 欧美激情中文字幕乱码免费| 亚洲黄色影片| 一本一本久久a久久精品综合妖精|