Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 34141 | Accepted: 11420 |
Descriptionnode
Inputless
Outputspa
Sample Inputcode
5 4 1 2 3 1 3 1 1 4 2 3 5 1 0 0
Sample Outputblog
8
題意就是給你一個帶邊權的樹,求樹上最短距離<=K的點對數量。樹分治模板題。遞歸
代碼:three
1 //樹分治-點分治 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 typedef long long ll; 10 const int inf=1e9+10; 11 const int maxn=1e5+10; 12 13 int head[maxn],tot; 14 int root,allnode,ans,n,k; 15 int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子節點個數(路徑長度),point爲重心節點 16 17 struct node{ 18 int to,next,val; 19 }edge[maxn<<1]; 20 21 void add(int u,int v,int w)//前向星存圖 22 { 23 edge[tot].to=v; 24 edge[tot].next=head[u]; 25 edge[tot].val=w; 26 head[u]=tot++; 27 } 28 29 void init()//初始化 30 { 31 memset(head,-1,sizeof head); 32 memset(vis,0,sizeof vis); 33 tot=0; 34 } 35 36 void get_root(int u,int father)//重心 37 { 38 siz[u]=1;point[u]=0; 39 for(int i=head[u];~i;i=edge[i].next){ 40 int v=edge[i].to; 41 if(v==father||vis[v]) continue; 42 get_root(v,u);//遞歸獲得子樹大小 43 siz[u]+=siz[v]; 44 point[u]=max(point[u],siz[v]);//更新u節點的point 45 } 46 point[u]=max(point[u],allnode-siz[u]);//保存節點size 47 if(point[u]<point[root]) root=u;//更新當前子樹的重心 48 } 49 50 void get_dis(int u,int father)//獲取子樹全部節點與根的距離 51 { 52 deep[++deep[0]]=dis[u]; 53 for(int i=head[u];~i;i=edge[i].next){ 54 int v=edge[i].to; 55 if(v==father||vis[v]) continue; 56 int w=edge[i].val; 57 dis[v]=dis[u]+w; 58 get_dis(v,u); 59 } 60 } 61 62 int cal(int u,int now) 63 { 64 dis[u]=now;deep[0]=0; 65 get_dis(u,0); 66 sort(deep+1,deep+deep[0]+1); 67 int all=0; 68 for(int l=1,r=deep[0];l<r;){//二分 69 if(deep[l]+deep[r]<=k){ 70 all+=r-l;l++; 71 } 72 else r--; 73 } 74 return all; 75 } 76 77 void solve(int u)//以u爲重心進行計算 78 { 79 ans+=cal(u,0);//以當前u爲重心的貢獻 80 vis[u]=1; 81 for(int i=head[u];~i;i=edge[i].next){ 82 int v=edge[i].to; 83 if(vis[v]) continue; 84 ans-=cal(v,edge[i].val);//減去子樹的影響 85 allnode=siz[v]; 86 root=0; 87 get_root(v,u); 88 solve(root); 89 } 90 } 91 92 int main() 93 { 94 while(~scanf("%d%d",&n,&k)&&n&&k){ 95 init(); 96 for(int i=1;i<n;i++){ 97 int u,v,w; 98 scanf("%d%d%d",&u,&v,&w); 99 add(u,v,w); 100 add(v,u,w); 101 } 102 root=ans=0; 103 allnode=n;point[0]=inf; 104 get_root(1,0); 105 solve(root); 106 printf("%d\n",ans); 107 } 108 return 0; 109 }
同樣的東西,就只是改了一下數據範圍和輸入格式。get
代碼:input
1 //樹分治-點分治 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<cmath> 8 using namespace std; 9 typedef long long ll; 10 const int inf=1e9+10; 11 const int maxn=4e4+10; 12 13 int head[maxn],tot; 14 int root,allnode,ans,n,k; 15 int vis[maxn],deep[maxn],dis[maxn],siz[maxn],point[maxn];//deep[0]子節點個數(路徑長度),point爲重心節點 16 17 struct node{ 18 int to,next,val; 19 }edge[maxn<<1]; 20 21 void add(int u,int v,int w)//前向星存圖 22 { 23 edge[tot].to=v; 24 edge[tot].next=head[u]; 25 edge[tot].val=w; 26 head[u]=tot++; 27 } 28 29 void init()//初始化 30 { 31 memset(head,-1,sizeof head); 32 memset(vis,0,sizeof vis); 33 tot=0; 34 } 35 36 void get_root(int u,int father)//重心 37 { 38 siz[u]=1;point[u]=0; 39 for(int i=head[u];~i;i=edge[i].next){ 40 int v=edge[i].to; 41 if(v==father||vis[v]) continue; 42 get_root(v,u);//遞歸獲得子樹大小 43 siz[u]+=siz[v]; 44 point[u]=max(point[u],siz[v]);//更新u節點的point 45 } 46 point[u]=max(point[u],allnode-siz[u]);//保存節點size 47 if(point[u]<point[root]) root=u;//更新當前子樹的重心 48 } 49 50 void get_dis(int u,int father)//獲取子樹全部節點與根的距離 51 { 52 deep[++deep[0]]=dis[u]; 53 for(int i=head[u];~i;i=edge[i].next){ 54 int v=edge[i].to; 55 if(v==father||vis[v]) continue; 56 int w=edge[i].val; 57 dis[v]=dis[u]+w; 58 get_dis(v,u); 59 } 60 } 61 62 int cal(int u,int now) 63 { 64 dis[u]=now;deep[0]=0; 65 get_dis(u,0); 66 sort(deep+1,deep+deep[0]+1); 67 int all=0; 68 for(int l=1,r=deep[0];l<r;){//二分 69 if(deep[l]+deep[r]<=k){ 70 all+=r-l;l++; 71 } 72 else r--; 73 } 74 return all; 75 } 76 77 void solve(int u)//以u爲重心進行計算 78 { 79 ans+=cal(u,0);//以當前u爲重心的貢獻 80 vis[u]=1; 81 for(int i=head[u];~i;i=edge[i].next){ 82 int v=edge[i].to; 83 if(vis[v]) continue; 84 ans-=cal(v,edge[i].val);//減去子樹的影響 85 allnode=siz[v]; 86 root=0; 87 get_root(v,u); 88 solve(root); 89 } 90 } 91 92 int main() 93 { 94 scanf("%d",&n); 95 init(); 96 for(int i=1;i<n;i++){ 97 int u,v,w; 98 scanf("%d%d%d",&u,&v,&w); 99 add(u,v,w); 100 add(v,u,w); 101 } 102 scanf("%d",&k); 103 root=ans=0; 104 allnode=n;point[0]=inf; 105 get_root(1,0); 106 solve(root); 107 printf("%d\n",ans); 108 return 0; 109 }