点分治算法很容易常数写大?不开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 }