zoukankan      html  css  js  c++  java
  • BZOJ 1086:[SCOI2005]王室联邦(DFS树分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1086

    题意:给出n个点的树,让你对树进行分块,每块的大小范围在[b, 3b]之间。

    思路:一开始想着维护一个sz[u]代表以u为根的子树(不包括u本身)的大小,如果在范围之内就分成一块,但是这样写感觉一些细节上的东西没考虑清楚,WA了很久。

    看了别人的做法:http://blog.csdn.net/popoqqq/article/details/42772237,很简洁。

    大概是维护一个栈,每次dfs结束的时候入栈,在每次遍历子树之前标记一下当前的栈顶,当遍历子树的时候,如果当前的栈顶 - 之前的栈顶 >= b的话,就可以分成一块了。最后剩下的元素和最后一块连通。

    结果的正确性:因为之前的子树大小加起来小于b,当前的子树大小小于b,所以当前的块大小小于2*b。最后剩余的元素小于b,最后的块小于2*b,因此小于3*b。

    因为b小于n的,所以可以保证一定有答案。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <vector>
     4 #include <algorithm>
     5 using namespace std;
     6 #define N 1010
     7 struct Edge {
     8     int v, nxt;
     9 } edge[N*2];
    10 int n, b, head[N], tot, belong[N], stk[N], top;
    11 vector<int> ans;
    12 
    13 void Add(int u, int v) {
    14     edge[tot] = (Edge) {v, head[u]}; head[u] = tot++;
    15     edge[tot] = (Edge) {u, head[v]}; head[v] = tot++;
    16 }
    17 
    18 void dfs(int u, int fa) {
    19     int base = top; // 之前的栈顶
    20     for(int i = head[u]; ~i; i = edge[i].nxt) {
    21         int v = edge[i].v;
    22         if(v == fa) continue;
    23         dfs(v, u);
    24         if(top - base >= b) {
    25             ans.push_back(u);
    26             while(base < top) belong[stk[top--]] = ans.size();
    27         }
    28     }
    29     stk[++top] = u;
    30 }
    31 
    32 int main() {
    33     while(~scanf("%d%d", &n, &b)) {
    34         memset(head, -1, sizeof(head)); tot = top = 0;
    35         memset(belong, -1, sizeof(belong));
    36         for(int i = 1; i < n; i++) {
    37             int u, v; scanf("%d%d", &u, &v);
    38             Add(u, v);
    39         }
    40         dfs(1, -1);
    41         while(top) belong[stk[top--]] = ans.size(); // 最后元素
    42         printf("%d
    ", ans.size());
    43         for(int i = 1; i <= n; i++) printf("%d%c", belong[i], i == n ? '
    ' : ' ');
    44         for(int i = 0; i < ans.size(); i++) printf("%d%c", ans[i], ans.size() - 1 == i ? '
    ' : ' ');
    45     }
    46     return 0;
    47 }
  • 相关阅读:
    ASP.NET常用信息保持状态学习笔记二
    初识HTTP协议请求与响应报文
    Linux下基于C的简单终端聊天程序
    Linux基于CURSES库下的二维菜单
    aspx与ashx
    linux下基于GTK窗口编程
    ajaxjquery无刷新分页
    asp.net管道模型(管线模型)(内容转载至博客园)
    ASP.NET常用信息保持状态学习笔记一
    ASP.NET使用管道模型(PipleLines)处理HTTP请求 (内容出自CSDN)
  • 原文地址:https://www.cnblogs.com/fightfordream/p/6433244.html
Copyright © 2011-2022 走看看