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

糯米

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>
            欧美aa国产视频| 中文有码久久| 亚洲欧美日韩综合一区| 久久这里只有| 日韩视频在线一区二区| 伊人婷婷欧美激情| 国产日韩欧美亚洲| 欧美性生交xxxxx久久久| 可以免费看不卡的av网站| 久久九九国产| 久久综合色播五月| 欧美成人中文字幕| 欧美激情视频在线播放| 亚洲一区日韩| 欧美一区三区三区高中清蜜桃| 亚洲综合好骚| 久久精品一区四区| 亚洲高清久久| 免费黄网站欧美| 亚洲精品中文字幕女同| 亚洲一区999| 免费欧美电影| 国产日本欧美视频| 亚洲伦理中文字幕| 久久欧美肥婆一二区| 最新日韩在线视频| 午夜一区不卡| 欧美日韩在线不卡一区| 亚洲高清不卡一区| 久久激情婷婷| 亚洲欧美日韩国产| 欧美四级剧情无删版影片| 亚洲国产三级网| 免费不卡视频| 久久成人一区| 亚洲第一在线综合网站| 久久精品视频一| 国产三区精品| 久久婷婷丁香| 久久久不卡网国产精品一区| 国产三级精品三级| 久久久五月婷婷| 久久久999成人| 一区二区三区在线不卡| 久久国产主播| 欧美成人四级电影| 99天天综合性| 亚洲女女女同性video| 国产亚洲毛片在线| 欧美成人自拍| 欧美日韩mv| 亚洲综合视频一区| 欧美高清视频一二三区| 亚洲欧美成人综合| 香蕉久久夜色精品国产| 国产精品尤物| 久久综合九色99| 久久精品综合| 中文有码久久| 99xxxx成人网| 欧美亚洲成人精品| 久久免费一区| 欧美久久久久久蜜桃| 久久国产精品99精品国产| 久久夜色精品国产欧美乱| 韩日欧美一区二区三区| 亚洲最新中文字幕| 亚洲国产精品福利| 午夜欧美精品久久久久久久| 欧美一区不卡| 亚洲一区影音先锋| 蜜桃伊人久久| 久久久99国产精品免费| 国产精品美女久久久久久免费| 久久久天天操| 国产精品黄视频| 一本色道久久88综合日韩精品| 尤物网精品视频| 另类亚洲自拍| 蜜桃av综合| 亚洲精选一区二区| 欧美日本亚洲视频| 91久久综合| 亚洲一区二区网站| 国产精品日韩欧美综合 | 亚洲黄色精品| 亚洲男人第一网站| 国产亚洲欧美日韩日本| 欧美成人精品三级在线观看| 亚洲精品日韩一| 亚洲欧美国产精品专区久久| 国产精品色网| 欧美14一18处毛片| 亚洲一区二区精品在线观看| 久久精品中文| 一区二区免费在线观看| 国产精品日韩二区| 欧美成人亚洲成人| 欧美专区福利在线| 亚洲私人影院| 亚洲精品乱码久久久久久黑人| 午夜亚洲福利在线老司机| 亚洲福利视频一区| 国产在线高清精品| 国产精品一二| 国产精品久久久久久久电影| 欧美成人免费一级人片100| 亚洲精品自在久久| 国内激情久久| 欧美成人在线影院| 久久视频这里只有精品| 中国成人黄色视屏| 99精品国产在热久久婷婷| 亚洲精选在线观看| 亚洲裸体视频| 亚洲视频精品在线| 亚洲午夜久久久| 日韩午夜激情电影| 亚洲午夜电影在线观看| 亚洲午夜久久久| 欧美亚洲在线观看| 久久久www成人免费精品| 久久九九精品| 欧美国产另类| 欧美日韩中文字幕精品| 亚洲素人在线| 久久精品二区| 亚洲欧洲一区| 在线中文字幕一区| 久久久久久网址| 国产精品xnxxcom| 亚洲丶国产丶欧美一区二区三区| 日韩一级精品| 免费成人性网站| 午夜国产精品视频| 蜜桃精品一区二区三区| 国产精品乱码久久久久久| 极品少妇一区二区三区| 亚洲摸下面视频| 亚洲激情电影在线| 亚洲欧洲av一区二区| 欧美深夜影院| 一本久道久久综合婷婷鲸鱼| 免费h精品视频在线播放| 欧美在线高清视频| 国产日韩精品一区二区| 亚洲一区二区三区激情| 亚洲人成人77777线观看| 亚洲福利电影| 一区二区三区视频在线播放| 美日韩精品免费| 亚洲国产精品t66y| 欧美福利专区| 欧美人与性动交α欧美精品济南到 | 久热成人在线视频| 亚洲国产成人在线播放| 欧美在线观看你懂的| 亚洲综合三区| 尤物yw午夜国产精品视频明星| 久久精品视频亚洲| 久久久精品动漫| 亚洲国产精品一区| 最新69国产成人精品视频免费| 欧美精品一区二区三区久久久竹菊 | 99视频精品免费观看| 另类天堂av| 国产女主播一区二区| 久久香蕉国产线看观看av| 亚洲欧美大片| 国产精品丝袜91| 美日韩在线观看| 欧美日韩国产精品| 99精品国产高清一区二区| 亚洲日本成人女熟在线观看| 国产麻豆精品视频| 欧美二区在线播放| 欧美日韩国产首页在线观看| 夜夜嗨av一区二区三区四区| 99精品视频免费观看| 欧美韩日一区| 久久女同精品一区二区| 欧美日韩中国免费专区在线看| 欧美日本三级| 免费成人av在线| 日韩亚洲欧美成人一区| 韩国av一区二区| 性欧美精品高清| 欧美一区视频在线| 国产精品视频内| 欧美国内亚洲| 一区二区视频免费在线观看| 亚洲欧美激情视频| 亚洲欧美国产77777| 欧美性猛交视频| 亚洲精品小视频在线观看| 亚洲精品123区| 老牛国产精品一区的观看方式| 久久视频一区二区| 国产一区二区中文| 久久精品亚洲|