PAT 1053 Path of Equal Weight
这一题的大意是在一棵树中找从根节点到叶子节点的所有路径中,其路径和等于S的路径。
很明显,面对这样树的题目,我们要想找到符合条件的路径,只能选择对所有路径进行遍历一遍,也就是dfs,在递归遍历的过程中找到当到达叶子节点是其路径和等于S值。记录在这个过程中经历过的点,关键点在dfs+回溯。
最开始我是这样写的:
#include <iostream>
#include <limits.h>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
int N;
int M;
long long S;
long long w[1005];
vector<vector<int>> endans;
struct Node
{int ID;vector<int> id;int k;
}node[1005];
void dfs(Node root,long long sum,vector<int>& ans)
{bool flag=0;for(int q=0;q<root.id.size();q++){flag=1;int nowid=root.id[q];ans.push_back(w[nowid]);dfs(node[nowid],sum+w[nowid],ans);ans.pop_back();}if(flag==0){//说明此时到了叶子节点if(sum==S){//说明符合条件 endans.push_back(ans);return ;}else{return;}}
}
bool cmp(int a,int b)
{if(w[a]>w[b]){return true;}else{return false;}
}
int main()
{//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>N>>M>>S;for(int i=0;i<N;i++){cin>>w[i];}for(int i=0;i<M;i++){int ID;int k;cin>>ID>>k;node[ID].ID=ID;node[ID].k=k;for(int j=0;j<node[ID].k;j++){int x;cin>>x;node[ID].id.push_back(x);}sort(node[ID].id.begin(),node[ID].id.end(),cmp);}int cnt=0;Node root=node[0];long long sum=w[0];vector<int> ans;ans.push_back(w[0]);for(int j=0;j<node[0].k;j++){int nowid=root.id[j];ans.push_back(w[nowid]);dfs(node[nowid],sum+w[nowid],ans);ans.pop_back();}for(int i=0;i<endans.size();i++){for(int j=0;j<endans[i].size();j++){if(j==0){cout<<endans[i][j];}else{cout<<" "<<endans[i][j];}}cout<<endl;}return 0;}
但这样会有两个测试点不过:
一个原因是,我的dfs在main函数中单独的写了一层,这就会导致如果只有根节点,且根节点还等于S,那么就不符合条件,因为在main函数中单独写的一层不涉及到其路径和等于S值的判断。
所以在写dfs的时候,一定要写规整。
那么改进后的代码
#include <iostream>
#include <limits.h>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
int N;
int M;
long long S;
long long w[1005];
vector<vector<int>> endans;
struct Node
{int ID;vector<int> id;int k;
}node[1005];
void dfs(Node root,long long sum,vector<int>& ans)
{bool flag=0;for(int q=0;q<root.id.size();q++){flag=1;int nowid=root.id[q];ans.push_back(w[nowid]);dfs(node[nowid],sum+w[nowid],ans);ans.pop_back();}if(flag==0){//说明此时到了叶子节点if(sum==S){//说明符合条件 endans.push_back(ans);return ;}else{return;}}
}
bool cmp(int a,int b)
{if(w[a]>w[b]){return true;}else{return false;}
}
int main()
{//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>N>>M>>S;for(int i=0;i<N;i++){cin>>w[i];}for(int i=0;i<M;i++){int ID;int k;cin>>ID>>k;node[ID].ID=ID;node[ID].k=k;for(int j=0;j<node[ID].k;j++){int x;cin>>x;node[ID].id.push_back(x);}sort(node[ID].id.begin(),node[ID].id.end(),cmp);}int cnt=0;Node root=node[0];long long sum=w[0];vector<int> ans;ans.push_back(w[0]);dfs(node[0],sum,ans);for(int i=0;i<endans.size();i++){for(int j=0;j<endans[i].size();j++){if(j==0){cout<<endans[i][j];}else{cout<<" "<<endans[i][j];}}cout<<endl;}return 0;
}
但还有一个测试用例不过:
这是因为有这样的一种可能,题目上说在最后输出序列的时候要按照相同位置从大到小输出,我们才用的解决办法是对同一层的节点进行一个排序,排序依据的是每一个节点的权值大小。这样权值大的就先被dfs遍历,权值小的就后被dfs遍历。
但还存在一种情况,就是同一层的节点的权值是相同的,那么就需要涉及到其子节点的大小比较,同一层的节点的权值相同,那么肯定要比较下一层的节点的权值,权值大的先输出。
例如
1
/ \
2 2
/ \
2 3
/ \
3 2
而我们写的这种排序方法没有考虑到。
因此我们选择不在输入的时候对其进行排序,
而是当所有的符合条件的路径都保存好,要输出之前,我们对要输出的数组进行排序:
#include <iostream>
#include <limits.h>
#include <cstring>
#include <queue>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
int N;
int M;
long long S;
long long w[1005];
vector<vector<int>> endans;
struct Node
{int ID;vector<int> id;int k;
}node[1005];
void dfs(Node root,long long sum,vector<int>& ans)
{bool flag=0;for(int q=0;q<root.id.size();q++){flag=1;int nowid=root.id[q];ans.push_back(w[nowid]);dfs(node[nowid],sum+w[nowid],ans);ans.pop_back();}if(flag==0){//说明此时到了叶子节点if(sum==S){//说明符合条件 endans.push_back(ans);return ;}else{return;}}
}
bool cmp(int a,int b)
{if(w[a]>w[b]){return true;}else{return false;}
}
int main()
{//ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);cin>>N>>M>>S;for(int i=0;i<N;i++){cin>>w[i];}for(int i=0;i<M;i++){int ID;int k;cin>>ID>>k;node[ID].ID=ID;node[ID].k=k;for(int j=0;j<node[ID].k;j++){int x;cin>>x;node[ID].id.push_back(x);}//sort(node[ID].id.begin(),node[ID].id.end(),cmp);}int cnt=0;Node root=node[0];long long sum=w[0];vector<int> ans;ans.push_back(w[0]);dfs(node[0],sum,ans);sort(endans.begin(), endans.end(), greater<vector<int>>());for(int i=0;i<endans.size();i++){for(int j=0;j<endans[i].size();j++){if(j==0){cout<<endans[i][j];}else{cout<<" "<<endans[i][j];}}cout<<endl;}return 0;}
这样就可以通过所有的测试用例。