1053. Path of Equal Weight (30)
Given a non-empty tree with root R, and with weight Wi assigned to each tree node Ti. The weight of a path from R to L is defined to be the sum of the weights of all the nodes along the path from R to any leaf node L.
Now given any weighted tree, you are supposed to find all the paths with their weights equal to a given number. For example, let's consider the tree showed in Figure 1: for each node, the upper number is the node ID which is a two-digit number, and the lower number is the weight of that node. Suppose that the given number is 24, then there exists 4 different paths which have the same given weight: {10 5 2 7}, {10 4 10}, {10 3 3 6 2} and {10 3 3 6 2}, which correspond to the red edges in Figure 1.
Figure 1
Input Specification:
Each input file contains one test case. Each case starts with a line containing 0 < N <= 100, the number of nodes in a tree, M (< N), the number of non-leaf nodes, and 0 < S < 230, the given weight number. The next line contains N positive numbers where Wi (<1000) corresponds to the tree node Ti. Then M lines follow, each in the format:
ID K ID[1] ID[2] ... ID[K]
where ID is a two-digit number representing a given non-leaf node, K is the number of its children, followed by a sequence of two-digit ID's of its children. For the sake of simplicity, let us fix the root ID to be 00.
Output Specification:
For each test case, print all the paths with weight S in non-increasing order. Each path occupies a line with printed weights from the root to the leaf in order. All the numbers must be separated by a space with no extra space at the end of the line.
Note: sequence {A1, A2, ..., An} is said to be greater than sequence {B1, B2, ..., Bm} if there exists 1 <= k < min{n, m} such that Ai = Bi for i=1, ... k, and Ak+1 > Bk+1.
Sample Input:20 9 24 10 2 4 3 5 10 2 18 9 7 2 2 1 3 12 1 8 6 2 2 00 4 01 02 03 04 02 1 05 04 2 06 07 03 3 11 12 13 06 1 09 07 2 08 10 16 1 15 13 3 14 16 17 17 2 18 19Sample Output:
10 5 2 7 10 4 10 10 3 3 6 2 10 3 3 6 2
这道题的测试数据有漏洞:
例子:A节点的子节点插入时,只根据A的子节点的值的大小就决定了先后顺序。如果要求最后的和为10,A(v=3)的子节点有
B(v=2,子节点F(v=4,子节点G(v=1)))
C(v=2,子节点H(v=3,子节点I(v=2)))
D(v=4)
E(v=3),如果只根据一层的节点的值大小进行排序,(BC节点本身值相同时,根据其他条件判断BC的优先级,我写的代码中是按值相同情况下,再按序号降序排列)则恰巧C排在B后面,那么输出的序列应该先是A C H I和A B F G,但实际上根据题意输出序列应该是A B F G和A C H I,故测试数据有漏洞。
不信的话,可以将正文代码的20行 return a.num<num; 改为 return a.num>num; 再进行评判。
其实真的要做,恐怕要把每条路径记录后,进行比较后才能输出。
注意点:
1.计入子节点的时候,要对子节点进行排序,值较大的放在前面,方便后面的深度优先遍历。
2.注意树可能为空,根节点可能就直接符合条件。
3.关于set的比较函数:
set的比较函数的条件一定要能比出最终的结果,在每一级的比较条件排序后,最后一定能完全地比较出大小。(不存在优先级相等的元素)
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<queue> 6 #include<vector> 7 #include<cmath> 8 #include<string> 9 #include<map> 10 #include<set> 11 #include<stack> 12 using namespace std; 13 struct node{ 14 int num,v; 15 bool operator<(const node &a) const { 16 return a.v<v; 17 } 18 }; 19 node value[3]; 20 map<int,set<node> > tree; 21 int main(){ 22 //freopen("D:\INPUT.txt","r",stdin); 23 value[0].v=-1; 24 value[0].num=0; 25 tree[0].insert(value[0]); 26 value[1].v=-1; 27 value[1].num=1; 28 tree[0].insert(value[1]); 29 value[2].v=1; 30 value[2].num=2; 31 tree[0].insert(value[2]); 32 int i; 33 34 cout<<tree[0].size()<<endl; 35 36 set<node>::iterator it; 37 for(it=tree[0].begin();it!=tree[0].end();it++){ 38 cout<<it->num<<endl; 39 } 40 /*int n,m,s; 41 scanf("%d %d %d",&n,&m,&s); 42 int i,j; 43 for(i=0;i<n;i++){ 44 scanf("%d",value[i].v); 45 value[i].num=i; 46 } 47 int fir,num,amount; 48 for(i=0;i<m;i++){ 49 scanf("%d %d",&fir,&amount); 50 for(j=0;j<amount;j++){ 51 scanf("%d",&num); 52 tree[fir].insert(value[num]); 53 } 54 }*/ 55 56 return 0; 57 }
代码如下:
1 #include<cstdio> 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<queue> 6 #include<vector> 7 #include<cmath> 8 #include<string> 9 #include<map> 10 #include<set> 11 #include<stack> 12 using namespace std; 13 struct node //set比较函数中的比较条件不能出现相同,一定要能完全比较 14 { 15 int num,v; 16 bool operator<(const node &a) const //降序 17 { 18 if(a.v==v) 19 { 20 return a.num<num; 21 } 22 return a.v<v; 23 } 24 }; 25 node value[105]; 26 map<int,set<node> > tree; 27 int path[105];//记录前一个节点编号 28 int n,m,s; 29 queue<int> qq; 30 void DFS(int cur) 31 { 32 set<node>::iterator it; 33 for(it=tree[cur].begin(); it!=tree[cur].end(); it++) 34 { 35 value[it->num].v=value[cur].v+value[it->num].v; 36 37 //cout<<"father: "<<cur<<" "<<it->num<<" "<<it->v<<" "<<value[it->num].v<<endl; 38 39 if(!tree[it->num].size()&&value[it->num].v==s) //找到符合条件的叶节点 40 { 41 qq.push(it->num); 42 } 43 else 44 { 45 if(value[it->num].v>s) //剪枝 46 { 47 continue; 48 } 49 DFS(it->num);//q.push(it->num); 50 } 51 } 52 } 53 int main() 54 { 55 //freopen("D:\INPUT.txt","r",stdin); 56 scanf("%d %d %d",&n,&m,&s); 57 int i,j; 58 for(i=0; i<n; i++) 59 { 60 scanf("%d",&value[i].v); 61 value[i].num=i; 62 } 63 int fir,num,amount; 64 path[0]=0; 65 for(i=0; i<m; i++) //链接表 66 { 67 scanf("%d %d",&fir,&amount); 68 for(j=0; j<amount; j++) 69 { 70 scanf("%d",&num); 71 path[num]=fir; 72 tree[fir].insert(value[num]); 73 } 74 } 75 //queue<int> q,qq; 76 if(value[0].v==s){ 77 printf("%d ",s); 78 } 79 DFS(0); 80 /*q.push(0); 81 int cur; 82 set<node>::iterator it; 83 while(!q.empty()){ 84 cur=q.front(); 85 q.pop(); 86 for(it=tree[cur].begin();it!=tree[cur].end();it++){ 87 value[it->num].v=value[cur].v+value[it->num].v; 88 89 cout<<"father: "<<cur<<" "<<it->num<<" "<<it->v<<" "<<value[it->num].v<<endl; 90 91 if(!tree[it->num].size()&&value[it->num].v==s){//找到符合条件的叶节点 92 qq.push(it->num); 93 } 94 else{ 95 if(value[it->num].v>s){//剪枝 96 continue; 97 } 98 q.push(it->num); 99 } 100 } 101 }*/ 102 while(!qq.empty()) 103 { 104 stack<int> out; 105 int f=qq.front(); 106 qq.pop(); 107 for(i=f; path[i]!=i; i=path[i]) 108 { 109 out.push(i); 110 } 111 printf("%d",f=value[i].v);//out.push(i); 112 while(!out.empty()) 113 { 114 printf(" %d",value[out.top()].v-f); 115 f=value[out.top()].v; 116 out.pop(); 117 } 118 printf(" "); 119 } 120 return 0; 121 }