1. 程式人生 > >點分治:統計長度為K的路徑條數

點分治:統計長度為K的路徑條數

套用第一種點分治模板——先加後減法。
計算過程略微不同,得到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"); } }