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

糯米

TI DaVinci, gstreamer, ffmpeg
隨筆 - 167, 文章 - 0, 評(píng)論 - 47, 引用 - 0
數(shù)據(jù)加載中……

POJ 1987 Distance Statistics 牛題 樹(shù)的分治

這題很牛逼,是樓教主的《男人七題》的其中一道。
求:一棵樹(shù)內(nèi)最短距離小于K的點(diǎn)對(duì)數(shù)量
后來(lái)看了解題報(bào)告,原來(lái)樹(shù)也是可以分治的。

分:
選取一條邊,將一棵樹(shù)分成兩半,這兩半的節(jié)點(diǎn)數(shù)要盡量相等。
首先,統(tǒng)計(jì)個(gè)每個(gè)節(jié)點(diǎn)的下面有多少個(gè)節(jié)點(diǎn)
然后,就知道每個(gè)邊切斷之后的情況了。選擇最優(yōu)的即可。

治:
分成兩半之后,統(tǒng)計(jì)經(jīng)過(guò)該條邊的點(diǎn)對(duì)線段中,長(zhǎng)度小于K的數(shù)目。

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.


可見(jiàn)這位大牛的英文水平實(shí)在牛逼,英文說(shuō)得比中文說(shuō)得還清楚,贊一個(gè)。

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

后來(lái)找了一份能過(guò)1741的代碼,在http://hi.baidu.com/shingray/blog/item/221362b079afc55d082302f0.html
一個(gè)大牛的博客上~
發(fā)現(xiàn)它的思路不是選擇一條邊來(lái)把樹(shù)分成兩份。
而是選擇一個(gè)點(diǎn)來(lái)把樹(shù)分成數(shù)份,然后計(jì)算經(jīng)過(guò)該點(diǎn)的線段數(shù)目。
這樣速度就快了,大牛的代碼在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) 評(píng)論(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>
            日韩视频在线你懂得| 午夜欧美大片免费观看| 欧美天天在线| 性色一区二区| 免费看黄裸体一级大秀欧美| 亚洲六月丁香色婷婷综合久久| 国产精品伦一区| 午夜免费日韩视频| 亚洲高清不卡在线| 国产视频欧美视频| 免费不卡在线视频| 亚洲视频一区| 亚洲美女免费精品视频在线观看| 亚洲最新视频在线| 一区二区三区在线视频播放 | 欧美成人免费在线观看| 亚洲最新色图| 欧美韩日一区二区三区| 久久久天天操| 欧美一区二区三区啪啪| 在线天堂一区av电影| 欧美色123| 日韩午夜视频在线观看| 欧美成人r级一区二区三区| 国产精品亚洲视频| 先锋影音国产一区| 亚洲国产精品精华液2区45| 国产精品一卡二卡| 欧美日韩不卡合集视频| 久久综合伊人77777尤物| 久久精品最新地址| 亚洲欧美国产精品专区久久| 一区二区三区你懂的| 一区二区精品| 亚洲一区二区不卡免费| 亚洲欧美日韩视频二区| 亚洲午夜高清视频| 亚洲一区二区三区四区中文 | 国产精品一区视频| 久久免费精品日本久久中文字幕| 一区二区不卡在线视频 午夜欧美不卡在| 久久嫩草精品久久久精品| 韩国av一区| 国产欧美日韩| 国产在线视频欧美一区二区三区| 国产欧美 在线欧美| 国产美女精品视频| 国产在线精品一区二区夜色| 在线不卡中文字幕| 日韩视频在线观看国产| 一区二区三区欧美激情| 午夜精品久久久99热福利| 香蕉成人久久| 久久理论片午夜琪琪电影网| 亚洲国产精品久久久久婷婷884| 亚洲国产精品国自产拍av秋霞| 亚洲精品国产精品国产自| 99精品免费视频| 国产精品99久久99久久久二8| 欧美凹凸一区二区三区视频| 亚洲国产美女| 亚洲制服丝袜在线| 久久亚洲精品视频| 国产精品chinese| 黄色成人av在线| 99pao成人国产永久免费视频| 亚洲线精品一区二区三区八戒| 午夜在线观看欧美| 欧美成人首页| 这里是久久伊人| 久久久久久成人| 国产精品腿扒开做爽爽爽挤奶网站| 激情视频一区二区| 亚洲一区二区三区乱码aⅴ| 亚洲电影在线免费观看| 亚洲一区二区成人在线观看| 老司机久久99久久精品播放免费| 欧美亚洲视频在线观看| 一区二区视频欧美| 亚洲二区免费| 99视频精品全国免费| 亚洲一区二区三区精品在线观看| 久久综合久色欧美综合狠狠| 亚洲激情一区二区| 亚洲欧美日韩久久精品| 欧美精品一区二区蜜臀亚洲| 另类天堂视频在线观看| 国产精品二区在线| 伊人夜夜躁av伊人久久| 欧美在线视频观看| 在线视频你懂得一区二区三区| 亚洲一区二区三区久久| 午夜久久福利| 久久九九有精品国产23| 欧美在线视频在线播放完整版免费观看 | 亚洲欧美另类国产| 久久九九热免费视频| 欧美亚洲综合网| 欧美一区二区三区另类| 欧美日韩国产综合视频在线观看中文| 欧美日韩一区二区三区在线 | 欧美激情免费观看| 国内外成人免费视频 | 久久精精品视频| 亚洲精品久久久久久一区二区| 亚洲影视在线播放| 欧美视频一区二区三区…| 伊人久久亚洲美女图片| 午夜精品久久久久久久99热浪潮 | 亚洲电影免费观看高清完整版| 久久国产婷婷国产香蕉| 亚洲视频免费在线观看| 欧美日韩国产丝袜另类| 亚洲免费av网站| 亚洲国产天堂久久综合网| 久久人人97超碰人人澡爱香蕉| 国产欧美一区二区精品婷婷| 久久久久久久综合| 欧美一级欧美一级在线播放| 久久在线免费观看| 国产精品乱码一区二三区小蝌蚪| 亚洲精品久久久一区二区三区| 亚洲一区免费看| 亚洲自拍都市欧美小说| 欧美激情在线有限公司| 亚洲国产日韩欧美在线动漫| 在线观看91精品国产麻豆| 欧美视频在线观看视频极品 | 欧美在线二区| 亚洲欧美日本视频在线观看| 亚洲第一在线综合在线| 欧美成人综合网站| 亚洲图片欧洲图片av| 在线观看三级视频欧美| 久久综合久久久久88| 欧美二区在线| 国产精品国产a级| 伊人久久成人| 中文欧美在线视频| 久久伊人亚洲| 亚洲福利视频一区| 亚洲伊人观看| 欧美激情小视频| 欧美电影免费观看大全| 久久亚洲国产成人| 欧美日本在线| 亚洲私人影吧| 亚洲大黄网站| 亚洲日本免费| 欧美在线免费视屏| 国产一区二区三区精品久久久| 久久久久久久999| 欧美精品99| 久久久无码精品亚洲日韩按摩| 久久香蕉国产线看观看网| 亚洲午夜精品一区二区| 久久久国产精彩视频美女艺术照福利 | 久久在精品线影院精品国产| 亚洲一区自拍| 一本色道久久综合精品竹菊 | 日韩亚洲视频| 亚洲视频一区二区免费在线观看| 在线一区欧美| 欧美日韩一区在线观看视频| 99一区二区| 日韩亚洲不卡在线| 欧美精品自拍偷拍动漫精品| 亚洲欧美国产高清| 亚洲女同性videos| 亚洲调教视频在线观看| 欧美精品高清视频| 日韩视频在线一区二区三区| 亚洲综合色自拍一区| 欧美激情黄色片| 亚洲黄色免费| 亚洲国产精品v| 亚洲一区二区在线观看视频| av成人免费| 欧美日韩1区| 亚洲国产精品久久久久久女王| 欧美日韩精品一区二区三区四区| 久久亚洲综合色| 国外成人在线| 亚洲欧美一区二区视频| 欧美在线日韩在线| 国产三区精品| 久久精品在线播放| 噜噜噜在线观看免费视频日韩| 国产精品拍天天在线| 在线一区二区日韩| 翔田千里一区二区| 黄色小说综合网站| 欧美日韩午夜视频在线观看| 亚洲在线一区| 免费观看成人| 午夜精品免费在线| 日韩一级大片在线| 在线观看成人网| 欧美日韩国产小视频| 亚洲天堂av电影|