點分治:統計長度為K的路徑條數
阿新 • • 發佈:2019-01-25
套用第一種點分治模板——先加後減法。
計算過程略微不同,得到deep陣列後,計算和為K的路徑對數
1.剔除d[i]+d[i]==K的情況
2.遍歷一遍後,每種情況計算了兩次,最後需要除2
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<algorithm>
#include<limits.h>
#include<queue>
#include<vector>
#define ll long long
#define MP make_pair
#define MP(x,y) make_pair((x),(y))
#define X first
#define Y second
#define oo 0x3f3f3f3f
const ll INF = 0x0fffffffffffffff;
using namespace std;
typedef long long lld;
const int maxn = 10000+10;
int n,K;
typedef pair<int,int> F;
vector<F> e[maxn];
int s[maxn],deep[maxn],d[maxn],ans;
bool vis[maxn];
void add(int u,int v,int w) { e[u].push_back(MP(w,v)); }
F getcore(int u,int f,int sum){
s[u]=1;
int lar=0;
F ans=MP(oo,0);
for(int i=0;i<e[u].size();i++){
int v=e[u][i].Y;
if(v==f||vis[v]) continue;
F x=getcore(v,u,sum);
s[u]+=s[v];
lar=max(lar,s[v]);//記錄子樹節點的最大值
ans=min(ans,x);//記錄子樹結果的最小值(權值最小,然後編號最小)
}
lar=max(lar,sum-s[u]);
ans=min(ans,MP(lar,u));
return ans;
}
void build(){
for(int i=1;i<=n;i++) e[i].clear();
for(int i=1;i<=n;i++){
int v,w;
while(scanf("%d",&v)!=EOF&&v){
scanf("%d",&w);
add(i,v,w),add(v,i,w);
}
}
}
void getdeep(int u,int f){
deep[++deep[0]]=d[u];
for(int i=0;i<e[u].size();i++){
int v=e[u][i].Y,w=e[u][i].X;
if(v==f||vis[v]) continue;
d[v]=d[u]+w;
getdeep(v,u);
}
}
int cal(int u,int w){//統計初始長度為w,長度和不大於K的路徑個數(可重合)
d[u]=w,deep[0]=0,getdeep(u,-1);//得到以u為根節點,u的初始深度為w,其他點的深度
sort(deep+1,deep+deep[0]+1);
int tmp=0;
for(int i=1;i<=deep[0];i++){
int r=upper_bound(deep+1,deep+deep[0]+1,K-deep[i])-deep;
int l=lower_bound(deep+1,deep+deep[0]+1,K-deep[i])-deep;
tmp+=(r-l);
if(i>=l&&i<r) tmp--;
}
return tmp/2;
}
void work(int u,int f,int sum){
u=getcore(u,f,sum).Y;
ans+=cal(u,0);
vis[u]=1;
for(int i=0;i<e[u].size();i++){
int v=e[u][i].Y,c=e[u][i].X;
if(vis[v]||v==f) continue;
ans-=cal(v,c);
work(v,u,s[v]);
}
}
int main(){
// freopen("a.txt","r",stdin);
while(scanf("%d",&n)!=EOF&&n){
build();
scanf("%d",&K);
while(K){
memset(vis,0,sizeof(vis)),ans=0;
work(1,-1,n);
if(ans) printf("AYE\n");
else printf("NAY\n");
scanf("%d",&K);
}
printf(".\n");
}
}