题目给出一棵树(N<=10000)以及所有边的权(<=10000). 现在要求对任意查询Q(<=10^8), 判断是否存在一条边权之和恰好为Q的路径.
标程的方法暂时没看懂= =...
我用树的分治做(更多相关内容见09国家集训队漆子超的论文)
考虑一棵以root为根的子树, 那么在这棵子树中, 有多少条 v1->root->v2 的路径长恰好为Q呢? 可以先DFS一次子树, 求出所有点到root的距离, 将这些距离排个序, 就能在klogk的时间里求出满足和为Q的组合数count[root,Q]. 但是这样把路径重叠, 也就是v1->v'->root->v'->v2的情况也算进去了. 考虑不合法的状态, 如果有边重复, 那么其中肯定包含root到某个儿子的边, 也就是形如v1->chi->root->chi->v2. 所以count[root,Q]中不合法路径数为sigma(count[chi,Q-2*dist[root][chi]]), 求出来减去即可.
这样处理完以root为根的树后, 结点root已经没有用了. 也就是说剩下的只须处理它的所有儿子树, 转化为新的独立问题.
这样不断地处理树, 将树分成新子树, 最后完成所有子树的统计.
恰当选择每次拆分的树根可以使复杂度变成nlogn, 否则总复杂度仍然是n^2. 一个较方便的规则是: 选择树的平衡点, 也就是拿掉这个点后形成的森林里, max(|tree[i]|)最小.
这样的点可以对树DFS一次做DP求得. pku1655就是解决这个问题.
ps.pku1741与此题几乎完全一样, 唯一不同的是那题是求dist<=Q的路径的数量.
代码:
1
#include <iostream>
2
#include <algorithm>
3
using namespace std;
4
5
//#define DEBUG
6
7
const int MAX_V = 11000;
8
const int MAX_E = MAX_V*5;
9
10
struct EDGE
{
11
int v,e,w;
12
}edg[MAX_E];
13
int se, gg[MAX_V];
14
bool ok[MAX_E];
15
int vis[MAX_V], stamp;
16
int que[MAX_V*5], sque, pque;
17
int card[MAX_V], chm[MAX_V], sum[MAX_V], det[MAX_V];
18
int gdd[MAX_V],sdd;
19
int ans;
20
int N,L;
21
22
void addedge(int u, int v, int w)
23

{
24
edg[se].v=v; edg[se].w=w; edg[se].e=gg[u]; gg[u]=se++;
25
edg[se].v=u; edg[se].w=w; edg[se].e=gg[v]; gg[v]=se++;
26
}
27
28
void dfsplus(int rt, int ss, int di, int &idx, int &cnt)
29

{
30
//求距离的同时找重心
31
vis[rt]=stamp;
32
chm[rt]=0, card[rt]=1;
33
gdd[sdd++]=di;
34
for(int j=gg[rt]; j>0; j=edg[j].e)
{
35
if(ok[j])continue;
36
int v=edg[j].v;
37
if(vis[v]==stamp)continue;
38
dfsplus(v, ss, di+edg[j].w, idx, cnt);
39
card[rt]+=card[v];
40
chm[rt]=max(chm[rt],card[v]);
41
}
42
chm[rt]=max(chm[rt],ss-card[rt]);
43
if(chm[rt]<cnt)
44
idx=rt, cnt=chm[rt];
45
}
46
47
int matchdist(int d)
48

{
49
int ret=0;
50
sort(gdd,gdd+sdd);
51
int q1=0, q2=sdd-1;
52
//线性的扫描求组合数, 可惜前面的排序多了个logn
53
while(q1<=q2)
{
54
if(gdd[q1]+gdd[q2]<d)q1++;
55
else if(gdd[q1]+gdd[q2]>d)q2--;
56
else
{
57
if(gdd[q1]==gdd[q2])
{
58
ret+=(q2-q1)*(q2-q1+1)/2;
59
break;
60
}
61
else
{
62
int p1=q1+1, p2=q2-1;
63
while(p1<sdd && gdd[p1]==gdd[q1]) p1++;
64
while(p2>=0 && gdd[p2]==gdd[q2]) p2--;
65
ret+=(p1-q1)*(q2-p2);
66
q1=p1, q2=p2;
67
}
68
}
69
}
70
return ret;
71
}
72
73
void solve()
74

{
75
int i,j,k;
76
pque=sque=0;
77
ans=0;
78
stamp=0;
79
memset(vis,0,sizeof(vis));
80
det[1]=-1; sum[1]=N;
81
que[sque++]=1;
82
while(pque!=sque)
{
83
int u=que[pque++];
84
int idx=u, cnt=N+1;
85
sdd=0;
86
++stamp;
87
dfsplus(u, sum[u], 0, idx, cnt);
88
if(det[u]>0 && L-det[u]*2>=0)
{
89
//减去它父亲的非法路径数
90
ans-=matchdist(L-det[u]*2);
91
}
92
u=idx;
93
sdd=0;
94
++stamp;
95
dfsplus(u, sum[u], 0, idx, cnt);
96
//加上自己的总路径数
97
ans+=matchdist(L);
98
for(j=gg[u]; j>0; j=edg[j].e)
{
99
if(ok[j])continue;
100
int v=edg[j].v;
101
det[v]=edg[j].w;
102
ok[j^1]=true; //切断子树和父亲的边
103
sum[v]=card[v];
104
que[sque++]=v;
105
}
106
}
107
if(ans>0) puts("AYE");
108
else puts("NAY");
109
}
110
111
int main()
112

{
113
int i,j,k,u,v,w;
114
while(true)
{
115
scanf("%d",&N);
116
if(N==0)break;
117
se=2;
118
memset(gg,0,sizeof(gg));
119
for(u=1; u<=N; u++)
{
120
while(true)
{
121
scanf("%d",&v);
122
if(v==0)break;
123
scanf("%d",&w);
124
addedge(u,v,w);
125
}
126
}
127
while(true)
{
128
scanf("%d",&L);
129
if(L==0)break;
130
memset(ok,false,sizeof(ok));
131
solve();
132
}
133
printf(".\n");
134
}
135
}
136
posted on 2009-07-31 14:30
wolf5x 阅读(495)
评论(0) 编辑 收藏 引用 所属分类:
acm_icpc