【1053 30 dfs 树的路径和】 Path of Equal Weight
传送门
题意
给定 \(n\) 个节点,以及每个节点的权重 \(w_{i}\),\(m\) 个节点的出边关系,目标值 \(k\) ,每个关系为 \(id,k,id_{1},\dots,id_{k}\) ,即 \(id\) 节点的 \(k\) 条边的终点,求树中所有满足权重和为 \(k\) 的路径,这里指的是以根为起点,叶节点为终点的,输出路径中的每个点的权重,如果有多条,按照类似字典序的比较方式对不同路径按照从大到小顺序输出
数据范围
\(n\leq 100\)
题解
- 用存边的方式将图存储下来,利用结构体同时存储节点的权重 \(w_{i}\)
- 因为是按层遍历的,将某一节点的所有连点按照权重从大到小排序,输出时即为要求的顺序
dfs
求所有的路径,两个剪枝- 和大于要求值的时候剪枝
- 和等于要求值但是当前节点不是叶子节点
- 存取每个节点的上个节点,输出的时候根据这个找到对应权重输出即可
Code
#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define rep(i,a,n) for(int i=a;i<n;i++)
#define sz size
const int N=110;
vector<int>pre;
int n,m,k;
struct node{
int w;
vector<int>edge;
};
vector<node>a;
bool cmp(int x,int y){ return a[x].w>a[y].w;}
void dfs(int u,int sum){
if(sum>k) return;
if(sum==k){
if(a[u].edge.sz()) return;
vector<int>path;
int p=u;
path.pb(u);
while(p!=0){
p=pre[p];
path.pb(p);
}
reverse(path.begin(),path.end());
rep(i,0,path.sz()) {
if(i==path.sz()-1) printf("%d\n",a[path[i]].w);
else printf("%d ",a[path[i]].w);
}
}
rep(i,0,a[u].edge.sz()){
int v=a[u].edge[i];
pre[v]=u;
dfs(v,sum+a[v].w);
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
a.resize(n); pre.resize(n);
rep(i,0,n) scanf("%d",&a[i].w);
while(m--){
int id,p; scanf("%d%d",&id,&p);
a[id].edge.resize(p);
rep(i,0,p) scanf("%d",&a[id].edge[i]);
sort(a[id].edge.begin(),a[id].edge.end(),cmp);
}
dfs(0,a[0].w);
}