【PAT甲级 DFS和剪枝 树/图的遍历】1053 Path of Equal Weight (30分)

一刷

# include <iostream>
# include <queue>
# include <vector>
# include <algorithm>
using namespace std;

/*
在树中寻找符合长度的顶点路径,并根据路径的顺序输出路径中的每个顶点的权重
注意:路径必须以根节点为起点,叶子结点为终点。

输入格式:
		结点个数N 非叶子结点个数M 给定的权重S
	N个:
		结点00的权重   结点01的权重   ……   结点N-1的权重
	M行:
    	非叶子结点的子节点序号   子节点个数K   K个子节点的序号 
*/
typedef int INDEX;
struct node{
    
    
    int weight;
    vector<INDEX> child; // 存放子节点的序号
}Node[105];

int N, M, S;
vector<INDEX> path; // path存放的是路径中顶点的序号

void DFS(INDEX idx, int weightSum){
    
    
    //  剪枝(在这里剪枝也可以)
    // if(weightSum > S) return;
    
    // 当遍历到叶子结点(死胡同)
    if(Node[idx].child.size() == 0){
    
    
        // 找到了一条符合长度的路径,输出路径
        if(weightSum == S){
    
    
            for(size_t i = 0;i<path.size();++i){
    
    
                cout << Node[path[i]].weight;
                if(i != path.size() - 1)
                    cout << " ";
                else
                    cout << endl;
            }
        }
        return; // 不写也可以,因为出if后,在下面的for的条件判断一定不成立,还是会结束函数。
    }
    
    // 遍历所有子节点(岔路口)
    for(size_t i = 0;i<Node[idx].child.size();++i){
    
    
        INDEX cld = Node[idx].child[i]; // 当前节点的子节点的序号
        //  剪枝(如果加上该子节点的权重会超过给定的权重S, 说明这条路已经不需要再往深处走了)
        if(weightSum + Node[cld].weight <= S) {
    
    
            path.push_back(cld); // 将子节点加入到路径
            DFS(cld, weightSum + Node[cld].weight); // 去到当前节点的子节点,加上该子节点的权重以更新总权重
            path.pop_back();    // 从下层回溯上来之后,将加入的子节点从路径删除
        }
    }
}

int main(void){
    
    
    cin >> N >> M >> S;
    for(int i = 0;i<N;++i){
    
    
        scanf("%d", &Node[i].weight);
    }
    INDEX id, cid; // 当前节点的序号和其子节点的序号
    int K;
    for(int i = 0;i<M;++i){
    
    
        scanf("%d", &id);
        scanf("%d", &K);
        for(int j = 0;j<K;++j){
    
    
            scanf("%d", &cid);
            Node[id].child.push_back(cid);
        }
        // 从高到低排序当前节点的子节点,以便符合题目要求来输出
        sort(Node[id].child.begin(), Node[id].child.end(), [](INDEX a, INDEX b){
    
    return Node[a].weight > Node[b].weight;});
    }
    
    // 从根节点开始,必须要先将根节点处理了
    path.push_back(0);
    DFS(0, Node[0].weight);
    
    return 0;
}

二刷:精炼了很多

# include <bits/stdc++.h>
using namespace std;

int N, M, S;
vector<int> G[101];
int weight[101];
vector<int> rst;
void DFS(int u, int sumW){
    
    
    if(sumW > S) return;
    if(G[u].size() == 0 && sumW == S){
    
    
        rst.push_back(u);
        for(int i = 0;i < rst.size();++i)
            cout << weight[ rst[i] ] << (i == rst.size()-1 ? "\n" : " ");
        rst.pop_back();

        return;
    }
    rst.push_back(u);
    for(int v: G[u])
        DFS(v, sumW + weight[v]);
    rst.pop_back();
}

int main(){
    
    
    cin >> N >> M >> S;
    for(int i = 0;i < N;++i)
        scanf("%d", &weight[i]);
    for(int i = 0;i < M;++i){
    
    
        int u, K, v;
        scanf("%d %d", &u, &K);
        for(int j = 0;j < K;++j){
    
    
            scanf("%d", &v);
            G[u].push_back(v);
        }
        sort(G[u].begin(), G[u].end(), [](int a, int b){
    
    return weight[a] > weight[b];});
    }
    DFS(0, weight[0]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/MYMarcoreus/article/details/113527248