• luogu P3806 点分治1


    点分治算法很容易常数写大?不开O2就被卡常。

    很裸的点分治,从选出的根开始往其余的子树搜,看一下当前经过的路径长度tot,k-tot是否在set中,在就找到了长度为k的路径。唯一要注意下的就是,当前子树经过的路径长度不能直接丢到set里,要搞一个临时的tpset来暂存下,搜完这棵子树再把这个tpset的里的路径长度丢进set。避免误算一个子树里折返跑的情况。

      1 #include <cstdio>
      2 #include <set>
      3 #include <cstring>
      4 using namespace std;
      5 set <int> st,tp;
      6 const int MAXN = 10100,inf = 1000000000;
      7 int head[MAXN],siz[MAXN],to[MAXN * 2],nxt[MAXN * 2],val[MAXN * 2];
      8 int cnt,n,m,k,sum,root,maxn;
      9 bool vis[MAXN];
     10 bool suc;
     11 void add(int x,int y,int v)
     12 {
     13     nxt[++cnt] = head[x];
     14     to[cnt] = y;
     15     head[x] = cnt;
     16     val[cnt] = v;
     17 } 
     18 void get_root(int x,int frm)
     19 {
     20     int mx = 0;
     21     siz[x] = 1;
     22     for (int i = head[x];i;i = nxt[i])
     23     {
     24         if (vis[to[i]] == true || to[i] == frm) 
     25             continue; 
     26         get_root(to[i],x);
     27         mx = max(mx,siz[to[i]]);
     28         siz[x] += siz[to[i]];
     29     }
     30     mx = max(mx,sum - siz[x]);
     31     if (mx < maxn)
     32     {
     33         maxn = mx;
     34         root = x;
     35     }
     36 }
     37 void dfs(int x,int frm,int tot)
     38 {
     39     if (st.count(k - tot) == 1)
     40     {
     41         suc = true;
     42         return;
     43     }
     44     tp.insert(tot);
     45     for (int i = head[x];i;i = nxt[i])
     46     {
     47         if (vis[to[i]] == true || to[i] == frm)
     48             continue;
     49         dfs(to[i],x,tot + val[i]);
     50         if (suc) return;
     51     }
     52 }
     53 void pot_div(int x)
     54 {
     55     st.clear();
     56     st.insert(0);
     57     vis[x] = true;
     58     for (int i = head[x];i;i = nxt[i])
     59     {
     60         if (vis[to[i]] == true)
     61             continue;
     62         dfs(to[i],x,val[i]);
     63         if (suc) return;
     64         set <int> ::iterator it;
     65         for (it = tp.begin();it != tp.end();it++)
     66             st.insert(*it);
     67         tp.clear();
     68     }
     69     for (int i = head[x];i;i = nxt[i])
     70     {
     71         if (vis[to[i]] == true)
     72             continue;
     73         sum = siz[to[i]];
     74         maxn = inf;
     75         get_root(to[i],x);
     76         pot_div(root);
     77         if (suc) return;
     78     }
     79 }
     80 int main()
     81 {
     82     scanf("%d%d",&n,&m);
     83     int tx,ty,tw;
     84     for (int i = 1;i <= n - 1;i++)    
     85     {
     86         scanf("%d%d%d",&tx,&ty,&tw);
     87         add(tx,ty,tw);
     88         add(ty,tx,tw);
     89     }
     90     for (int i = 1;i <= m;i++)
     91     {
     92         suc = false;
     93         sum = n;
     94         maxn = inf;
     95         memset(vis,0,sizeof(vis));
     96         get_root(1,0);
     97         scanf("%d",&k);
     98         pot_div(root);
     99         if (suc)
    100             printf("AYE
    ");
    101         else
    102             printf("NAY
    ");
    103     }
    104     return 0;
    105 }
    心之所动 且就随缘去吧
  • 相关阅读:
    Linux Netcat命令
    clang-format
    keytool
    ip
    Linux iptables
    Linux yum源完全配置
    Makefile
    CMake
    HSTS
    开源镜像
  • 原文地址:https://www.cnblogs.com/iat14/p/10533125.html
Copyright © 2020-2023  润新知