版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengwill97/article/details/82562978
题意
给出一棵树,一些询问,询问树上是否有路径和为k的路径。
题解
发现询问只有100个,依次处理询问即可。
代码
这里依旧给出了两种写法, 一种是排序后利用单调性,一种是排序后二分。
利用单调性常数更小。
如果利用单调性,函数要返回
。因为认为u到v和v到u是不同路径。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
struct edge {
int to, nxt, w;
}e[10005 << 1];
int head[10005], tot;
void add_edge(int u, int v, int w) {
e[tot].to = v;
e[tot].nxt = head[u];
e[tot].w = w;
head[u] = tot++;
}
int n, m;
int sz[10005], root, nowmx, totnode, k, ans;
bool visit[10005];
void getroot(int u, int f) {
sz[u] = 1;
int mxpart = 0;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(v != f && !visit[v]) {
getroot(v, u);
sz[u] += sz[v];
mxpart = max(mxpart, sz[v]);
}
}
mxpart = max(mxpart, totnode - sz[u]);
if(mxpart < nowmx) {
nowmx = mxpart;
root = u;
}
}
int ss[10005], top;
void dfs(int u, int f, int d) {
if(d > k)
return;
ss[++top] = d;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(v != f && !visit[v]) {
dfs(v, u, d + e[i].w);
}
}
}
int getans(int u, int init) {
top = 0;
int cnt = 0;
dfs(u, u, init);
sort(ss + 1, ss + 1 + top);
int l = 1, r = top;
while(l < r) {
if(ss[l] + ss[r] > k) r --;
else if(ss[l] + ss[r] < k) l ++;
else {
if(ss[l] == ss[r]) {
cnt += (r - l + 1) * (r - l) /2;
break;
} else {
int i = l, j = r;
while(ss[l] == ss[i]) i++;
while(ss[r] == ss[j]) j--;
int tmp = (i - l) * (r - j);
cnt += tmp;
l = i;
r = j;
}
}
}
// }
// int mid = (top + 1)/ 2 ;
// for(int i = 1; i <= top; ++i)
// printf("%d ",ss[i]);
// printf("\n");
// for(int i = 1; i <= top; ++i) {
// int posl = lower_bound(ss + 1, ss + 1 + top, k - ss[i]) - (ss);
// int posr = upper_bound(ss + 1, ss + 1 + top, k - ss[i]) - (ss);
//// printf("debug %d %d %d\n", ss[i], posl, posr);
// if(ss[i] + ss[posl] == k && ss[i] == ss[posl]) {
// if(posr - posl - 1 > 0) {
// cnt += posr - posl - 1;
//// printf("in %d %d\n",ss[i], posr - posl - 1);
// }
// } else if(ss[i] + ss[posl] == k) {
// cnt += posr - posl;
//// printf("in %d %d\n",ss[i], posr - posl + 1);
// }
// }
return cnt;
}
void solve(int u) {
ans += getans(u, 0);
visit[u] = true;
for(int i = head[u]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if(!visit[v]) {
ans -= getans(v, e[i].w);
nowmx = INF; root = 0; totnode = sz[v];
getroot(v, u);
solve(root);
}
}
}
int main(){
while(scanf("%d", &n) && n) {
memset(head, -1, sizeof head);
tot = 0;
for(int i = 1 ; i <= n; ++i) {
int v, w;
while(scanf("%d", &v) && v) {
scanf("%d", &w);
add_edge(i, v, w);
add_edge(v, i ,w);
}
}
while(scanf("%d", &k) && k) {
ans = 0; totnode = n; nowmx = INF; root = 0;
memset(visit, 0, sizeof visit);
getroot(1, -1);
solve(root);
if(ans == 0) printf("NAY\n");
else printf("AYE\n");
}
printf(".\n");
}
return 0;
}