zoukankan      html  css  js  c++  java
  • 树的点分治 (poj 1741, 1655(树形dp))

    poj 1655:http://poj.org/problem?id=1655

    题意: 给无根树,  找出以一节点为根,  使节点最多的树,节点最少。

    题解:一道树形dp,先dfs 标记 所有节点的子树的节点数。 再dfs  找出以某节点为根的最大子树,节点最少。 复杂度(n)

    /***Good Luck***/
    #define _CRT_SECURE_NO_WARNINGS
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <stack>
    #include <map>
    #include <queue>
    #include <vector>
    #include <set>
    #include <functional>
    #include <cmath>
    
    #define Zero(a) memset(a, 0, sizeof(a))
    #define Neg(a)  memset(a, -1, sizeof(a))
    #define All(a) a.begin(), a.end()
    #define PB push_back
    #define inf 0x7fffffff
    #define inf2 0x7fffffffffffffff
    #define ll long long
    using namespace std;
    
    const int maxn = 100000;
    int n, k, e, head[maxn];
    int mx[maxn], sum[maxn], ansn, ansb;
    struct Node {
        int next, v;
    }node[maxn];
    
    void input(int u, int v) {
        node[e].next = head[u];
        node[e].v = v;
        head[u] = e++;
    }
    
    int dfssize(int b, int fa) {
        sum[b] = 1;
        mx[b] = 0;
        int tmpmx;
        for (int i = head[b]; ~i; i = node[i].next) {
            int v = node[i].v;
            if (fa != v) {
                tmpmx = dfssize(v, b);
                sum[b] +=tmpmx;            
                if (tmpmx > mx[b]) mx[b] = tmpmx;
            }
        }
        return sum[b];
    }
    
    void solve(int b, int fa) {
        int tmpmx;
        tmpmx = max(mx[b], n - sum[b]);
        if (tmpmx <= ansb) {
            if (tmpmx < ansb) {
                ansn = b;
                ansb = tmpmx;
            } else if (b < ansn) {
                ansn = b;
                ansb = tmpmx;
            }
        }
        for (int i = head[b]; ~i; i = node[i].next) {
            int v = node[i].v;
            if (fa != v) {
                solve(v, b);
            }
        }
    }
    
    int main() {
        int u, v;
        int T;
        scanf("%d", &T);
        while (T-- ) {
            scanf("%d", &n);
            e = 0;
            Neg(head);
            for (int i = 0; i < n - 1; ++i) {
                scanf("%d%d", &u, &v);
                input(u, v);
                input(v, u);
            }
            dfssize(1, 0);
            ansb = inf;
            solve(1, 0);
            printf("%d %d
    ", ansn, ansb);
        }
        return 0;
    }
    View Code

    poj 1741:http://poj.org/problem?id=1741

    题意:给一值k,在带权无向图G中, 找出两节点相距不大于k的数。 

      qzc论文的第一题(膜拜q神  orz),根据论文写的 代码, 先写了一题树形dp(1655),再开始写这的,搞了一晚上具体的还是看论文吧。

    找根(n), 计算(logn), 一共执行 logn次  总复杂度(n*logn*logn)

      1 /***Good Luck***/
      2 #define _CRT_SECURE_NO_WARNINGS
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <cstdlib>
      6 #include <cstring>
      7 #include <string>
      8 #include <algorithm>
      9 #include <stack>
     10 #include <map>
     11 #include <queue>
     12 #include <vector>
     13 #include <set>
     14 #include <functional>
     15 #include <cmath>
     16 
     17 #define Zero(a) memset(a, 0, sizeof(a))
     18 #define Neg(a)  memset(a, -1, sizeof(a))
     19 #define All(a) a.begin(), a.end()
     20 #define PB push_back
     21 #define inf 0x3f3f3f3f
     22 #define inf2 0x7fffffffffffffff
     23 #define ll long long
     24 using namespace std;
     25 const int maxn = 20000;
     26 int head[maxn], n, k, e;
     27 int ans, sum[maxn], mx[maxn];
     28 bool vis[maxn];
     29 int dis[maxn], a[maxn], an;
     30 struct Node {
     31     int w;
     32     int v, next;
     33 }edge[maxn];
     34 
     35 void init() {
     36     e = 0;
     37     ans = 0;
     38     Neg(head);
     39     Zero(vis);
     40 }
     41 
     42 void add(int u, int v, int w) { //邻接表储存
     43     edge[e].v = v;
     44     edge[e].w = w;
     45     edge[e].next = head[u];
     46     head[u] = e++;
     47 }
     48 
     49 int dfssize(int u, int fa) {  //标记子树的节点数
     50     sum[u] = 1;
     51     mx[u] = 0;
     52     int tmpmx;
     53     for (int i = head[u]; ~i; i = edge[i].next) {
     54         int v = edge[i].v;
     55         if (v != fa && !vis[v]) {
     56             tmpmx = dfssize(v, u);
     57             sum[u] += tmpmx;
     58             if (tmpmx > mx[u]) mx[u] = tmpmx;
     59         }
     60     }
     61     return sum[u];
     62 }
     63 
     64 int ansn, mxshu;
     65 void find_root(int u, int fa, int nn) {  // 找出符合条件的根。
     66     int tmpmx = max(mx[u], nn - sum[u]);
     67     if (tmpmx < mxshu) {
     68         ansn = u;
     69         mxshu = tmpmx;
     70     }
     71     for (int i = head[u]; ~i; i = edge[i].next) {
     72         int v = edge[i].v;
     73         if (v != fa && !vis[v]) {
     74             find_root(v, u, nn);
     75         }
     76     }
     77 }
     78 
     79 void dfsdis(int u, int fa) {
     80     a[an++] = dis[u];
     81     for (int i = head[u]; ~i; i = edge[i].next) {
     82         int v = edge[i].v;
     83         if (fa != v && !vis[v]) {
     84             dis[v] = dis[u] + edge[i].w;
     85             dfsdis(v, u);
     86         }
     87     }
     88 }
     89 
     90 int cal(int u, int fa, int beg) {  //  这个方法太神奇了 复杂度只有 (logn)
     91     an = 0;
     92     int ret = 0;
     93     dis[u] = beg;
     94     dfsdis(u, fa);
     95     sort(a, a + an);
     96     int l = 0, r = an - 1;
     97     while (l < r) {
     98         if (a[r] + a[l] <= k )
     99             ret += r - l++;
    100         else
    101             r--;
    102     }
    103     return ret;
    104 }
    105 
    106 void solve(int u) {
    107     dfssize(u, 0);
    108     mxshu = inf;
    109     find_root(u, 0, sum[u]);
    110     vis[ansn] = true;
    111     ans += cal(ansn, 0, 0);
    112     for (int i = head[ansn]; ~i; i = edge[i].next) {
    113         int v = edge[i].v;
    114         if (!vis[v]) {
    115             ans -= cal(v, ansn, edge[i].w);
    116             solve(v);
    117         }
    118     }
    119 }
    120 int main() {
    121     //freopen("data.out", "w", stdout);
    122     //freopen("data.in", "r", stdin);
    123     int u, v, w;
    124     while (scanf("%d%d", &n, &k), n&&k) {
    125         init();
    126         for (int i = 0; i < n - 1; ++i) {
    127             scanf("%d%d%d", &u, &v, &w);
    128             add(u, v, w);
    129             add(v, u, w);
    130         }
    131         solve(1);
    132         printf("%d
    ", ans);
    133     }
    134     return 0;
    135 }

     

  • 相关阅读:
    pikachu——Unsafe Filedownload Fileupload(不安全的文件下载和上传)
    pikachu——Files Inclusion(文件包含漏洞)
    pikachu——RCE
    pikachu——SQL注入
    pikachu——XSS(跨网站脚本漏洞)
    pikachu——CSRF
    pikachu——暴力破解
    GCD 信号量 dispatch_semaphore_t
    【转】iOS 9 Storyboard 教程(一上)
    一个大小为N的数组,里面是N个整数,怎样去除重复的数
  • 原文地址:https://www.cnblogs.com/yeahpeng/p/3898994.html
Copyright © 2011-2022 走看看