洛谷P3252 [JLOI2012]树
生活随笔
收集整理的這篇文章主要介紹了
洛谷P3252 [JLOI2012]树
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目描述
在這個問題中,給定一個值S和一棵樹。在樹的每個節(jié)點有一個正整數(shù),問有多少條路徑的節(jié)點總和達到S。路徑中節(jié)點的深度必須是升序的。假設(shè)節(jié)點1是根節(jié)點,根的深度是0,它的兒子節(jié)點的深度為1。路徑不必一定從根節(jié)點開始。
輸入輸出格式
輸入格式:
?
第一行是兩個整數(shù)N和S,其中N是樹的節(jié)點數(shù)。 第二行是N個正整數(shù),第i個整數(shù)表示節(jié)點i的正整數(shù)。 接下來的N-1行每行是2個整數(shù)x和y,表示y是x的兒子。
?
輸出格式:
?
輸出路徑節(jié)點總和為S的路徑數(shù)量。
?
輸入輸出樣例
輸入樣例#1:3 3
1 2 3
1 2
1 3 輸出樣例#1:2 說明
對于100%數(shù)據(jù),N<=100000,所有權(quán)值以及S都不超過1000。
?
題目大意:求樹上連續(xù)一段深度遞增的路徑的點權(quán)和為s的條數(shù)
題解:dfs(i)以i為起點的路徑有多少條?
錯因:理解錯了 不能用記憶化搜索
數(shù)據(jù)水暴力可過
代碼:
#include<iostream> #include<cstdio> #include<cstring> #define LL long long #define maxn 100008 using namespace std;int n,s,sumedge; int head[maxn],w[maxn]; long long ans;struct Edge{int x,y,nxt;Edge(int x=0,int y=0,int nxt=0):x(x),y(y),nxt(nxt){} }edge[maxn];void add(int x,int y){edge[++sumedge]=Edge(x,y,head[x]);head[x]=sumedge; }LL dfs(int x,int sum){if(sum>s)return 0;if(sum==s)return 1;long long js=0;for(int i=head[x];i;i=edge[i].nxt){int v=edge[i].y;js+=dfs(v,sum+w[v]);}return js; }int main(){scanf("%d%d",&n,&s);for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);}for(int i=1;i<=n;i++)if(w[i]==s)ans++;else ans+=dfs(i,w[i]);cout<<ans<<endl;return 0; }
樹上前綴和
保存搜到i之前的祖先,累加權(quán)值,是否sum[i]-sum[祖先]=s,注意搜完時刪掉祖先。
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100008 #define LL long long using namespace std;int n,s,sumedge,cnt,js; int head[maxn],w[maxn],dad[maxn],fa[maxn],sum[maxn]; LL ans;struct Edge{int x,y,nxt;Edge(int x=0,int y=0,int nxt=0):x(x),y(y),nxt(nxt){} }edge[maxn];void add(int x,int y){edge[++sumedge]=Edge(x,y,head[x]);head[x]=sumedge; }void dfs(int x){dad[++js]=x;for(int i=head[x];i;i=edge[i].nxt){int v=edge[i].y;sum[v]=sum[x]+w[v];for(int j=js;j>=0;j--){//要循環(huán)到0,可能它自己的點權(quán)就是s if(sum[v]-sum[dad[j]]==s)ans++;if(sum[v]-sum[dad[j]]>s)break;}dfs(v);}js--; }int main(){scanf("%d%d",&n,&s);for(int i=1;i<=n;i++)scanf("%d",&w[i]);for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);fa[y]=x;add(x,y);}sum[1]=w[1]; dfs(1);cout<<ans<<endl;return 0; }
?
轉(zhuǎn)載于:https://www.cnblogs.com/zzyh/p/7593079.html
總結(jié)
以上是生活随笔為你收集整理的洛谷P3252 [JLOI2012]树的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 南京京科能看男科吗,我感觉自己好像那方面
- 下一篇: 求一个qq恐怖网名。