1053 Path of Equal Weight (30 分)

\(30\)分水了啊。

题意

给定一棵树和每个结点的权值,求所有从根结点到叶子结点的路径,使得每条路径上结点的权值之和等于给定的常数S。如果有多条这样的路径,按路径非递增的顺序输出。

其中路径的大小是指,如果两条路径分别为\(a_l→a_2→\cdots→a_i→a_n\)\(b_1→b_2→\cdots→b_i→b_m\),且有\(a_1=b_1、a_2=b_2\cdots 、a_{i-1}=b_{i-1}\)成立,但\(a_i>b_i\),那么称第一条路径比第二条路径大。

思路

  1. 若sum>S,直接return。
  2. 若sum==S,说明到当前访问结点index为止,输入中需要达到的S已经得到,这时如果结点index为叶子结点,则输出path数组中的所有数据;否则return。
  3. 若sum<S,说明要求还未满足。此时枚举当前访问结点index的所有子结点,对每一个子结点child,先将其存入path,然后在此基础上往下一层递归。

注意点

  1. vector是可以直接比较大小的,比较标准为字典序。
  2. 题目要求是从根结点到叶结点的路径,所以在递归过程中出现sum = S时必须判断当前访问结点是否是叶结点(即是否有子结点)。只有当前访问结点不是叶结点,才能输出路径,如果不是叶结点,则必须返回。
const int N=110;
vector<int> g[N];
int weight[N];
vector<vector<int>> ans;
vector<int> res;
int n,m,target;

void dfs(int u,int sum)
{
    if(sum > target) return;

    if(sum == target)
    {
        if(g[u].size() == 0)
            ans.push_back(res);
        return;
    }
    
    for(int i=0;i<g[u].size();i++)
    {
        int j=g[u][i];
        res.push_back(weight[j]);
        dfs(j,sum+weight[j]);
        res.pop_back();
    }
}

int main()
{
    cin>>n>>m>>target;

    for(int i=0;i<n;i++) cin>>weight[i];

    while(m--)
    {
        int u,k;
        cin>>u>>k;
        for(int i=0;i<k;i++)
        {
            int v;
            cin>>v;
            g[u].pb(v);
        }
    }

    res.pb(weight[0]);
    dfs(0,weight[0]);

    sort(ans.begin(),ans.end(),greater<vector<int>>());
    for(auto &v:ans)
    {
        for(int i=0;i<v.size();i++)
            if(i) cout<<' '<<v[i];
            else cout<<v[i];
        cout<<endl;
    }
    //system("pause");
    return 0;
}

考虑到最后的输出需要按权值从大到小排序,也可以在读入时就事先对每个结点的子结点vector进行排序(即对vector中的结点按权值从大到小排序),这样在遍历时就会优先遍历到权值大的子结点。

posted @ 2021-02-23 23:25  Dazzling!  阅读(70)  评论(0编辑  收藏  举报