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

糯米

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>
            国产精品一区二区你懂得| 亚洲第一在线视频| 欧美色视频日本高清在线观看| 亚洲欧洲av一区二区三区久久| 在线免费日韩片| 黑人巨大精品欧美黑白配亚洲| 久久久精品午夜少妇| 西西裸体人体做爰大胆久久久| 久久九九久精品国产免费直播| 1024成人网色www| 亚洲激情影院| 亚洲一区二区伦理| 久久精品一区二区三区不卡牛牛| 亚洲激情视频在线播放| 亚洲精品一区二区网址| 在线综合亚洲| 久久久久国产精品www| 免费日韩av电影| 亚洲欧洲一区二区在线播放| 亚洲深夜福利视频| 久久国产精品72免费观看| 亚洲国产精品久久久久秋霞不卡 | 中文av一区特黄| 亚洲专区一区| 欧美jizz19hd性欧美| 一区二区不卡在线视频 午夜欧美不卡在 | 久久成人一区| 免费观看日韩av| 日韩视频中文字幕| 性欧美大战久久久久久久免费观看 | 亚洲电影第三页| 99国产精品久久久久久久久久| 好吊妞**欧美| 激情欧美一区二区三区| 亚洲特色特黄| 亚洲国产精品久久人人爱蜜臀 | 欧美国产一区在线| 亚洲影音一区| 欧美日韩亚洲一区二区| 在线观看精品| 欧美在线电影| 亚洲香蕉伊综合在人在线视看| 亚洲国产欧美在线人成| 亚洲欧美综合| 欧美亚韩一区| 亚洲视频一区在线| 亚洲观看高清完整版在线观看| 一本大道久久a久久精品综合| 在线日本成人| 久久久久久久一区二区三区| 日韩午夜电影av| 欧美人成在线| 亚洲视频第一页| 一本色道久久综合亚洲91| 欧美日韩一本到| 亚洲一区bb| 亚洲天堂av电影| 国产精品视频内| 欧美亚洲视频在线观看| 中国亚洲黄色| 国产精品久久久久久福利一牛影视| 欧美日韩在线播放一区| 亚洲免费av电影| 日韩午夜激情| 国产精品高潮呻吟久久av无限| 欧美尤物一区| 一区二区三区日韩欧美精品| 久久电影一区| 欧美伊人精品成人久久综合97| 亚洲欧美日韩国产一区二区三区| 亚洲香蕉成视频在线观看| 欧美日韩在线播| 午夜亚洲精品| 久久av最新网址| 亚洲国产天堂久久综合| 亚洲国产成人午夜在线一区| 欧美成人资源| 亚洲欧美美女| 久久九九久久九九| 91久久久久久国产精品| 日韩小视频在线观看专区| 国产精品久久久久久久电影 | 亚洲人成亚洲人成在线观看| 久久欧美中文字幕| 一区二区高清在线| 国外视频精品毛片| 欧美高清视频免费观看| 欧美久久九九| 久久精品亚洲热| 欧美成人影音| 久久激情五月丁香伊人| 美女精品在线| 欧美在线看片| 欧美福利专区| 欧美一级淫片aaaaaaa视频| 久久久久久久综合| 亚洲欧美日韩视频二区| 理论片一区二区在线| 先锋影音久久| 欧美日韩一区二区在线| 欧美成人精品福利| 国产日韩一区在线| 99精品视频免费观看| 亚洲国产视频直播| 亚洲综合色网站| 亚洲最黄网站| 欧美成人国产| 欧美成人午夜激情视频| 国产日韩欧美不卡| 一区二区三区日韩精品| 9色国产精品| 欧美成人精品影院| 久久久久久久一区| 国产精品影片在线观看| 亚洲肉体裸体xxxx137| 激情亚洲网站| 亚洲一区二区成人| 一本一本久久| 欧美激情aaaa| 亚洲国产成人一区| 国模套图日韩精品一区二区| 亚洲巨乳在线| 亚洲视频观看| 欧美网站在线观看| 亚洲精品一区在线观看香蕉| 亚洲精品日韩一| 久久久久综合一区二区三区| 欧美一区二区三区精品电影| 激情文学一区| 亚洲欧洲精品成人久久奇米网| 一本色道久久综合精品竹菊 | 午夜视频在线观看一区二区| 一本久久综合| 欧美三级精品| 亚洲美女在线国产| 亚洲最新在线视频| 久热精品视频在线| 久久一二三四| 一区二区在线看| 久久影视精品| 亚洲区一区二| 日韩视频三区| 久久久亚洲高清| 国产欧美精品日韩| 性欧美长视频| 欧美资源在线| 在线观看日韩国产| 欧美xart系列高清| 亚洲国产欧美日韩| 一本色道久久88综合日韩精品| 亚洲国产精品美女| 亚洲国产精品123| 免费h精品视频在线播放| 欧美96在线丨欧| 亚洲电影一级黄| 欧美区在线播放| 一区二区三区视频在线| 欧美在线视频免费播放| 国产一区二区三区在线观看网站| 久久综合一区| 亚洲国产成人久久| 美日韩在线观看| 亚洲大片精品永久免费| 亚洲一区久久久| 精品白丝av| 欧美日韩中文字幕日韩欧美| 欧美一级欧美一级在线播放| 久久亚洲电影| 亚洲午夜精品久久| 国产日韩精品一区| 亚洲精品国产精品国自产观看浪潮| 久久中文字幕导航| 亚洲国产成人91精品| 亚洲欧美成aⅴ人在线观看| 国产伊人精品| 久久激情综合网| 亚洲美女网站| 蜜桃av综合| 欧美一区二区视频在线观看| 激情一区二区三区| 欧美性理论片在线观看片免费| 久久gogo国模裸体人体| 亚洲人成毛片在线播放女女| 国产精品国产自产拍高清av| 老司机精品视频网站| 亚洲欧美卡通另类91av| 亚洲精品日韩在线观看| 久久岛国电影| 亚洲在线一区二区三区| 日韩午夜电影| 亚洲第一在线| 精品99视频| 国内精品久久久久久久影视麻豆| 亚洲欧美国产高清| 最新日韩精品| 亚洲黄色在线看| 亚洲国产精品成人综合| 国产精品成人免费| 欲色影视综合吧| 国产日韩综合一区二区性色av|