第七次数据结构收官咯

有两题需要用时间。

7-3 二叉树最短路径长度 (100 分)

给定一棵二叉树T,每个结点赋一个权值。计算从根结点到所有结点的最短路径长度。路径长度定义为:路径上的每个顶点的权值和。

输入格式:

第1行,1个整数n,表示二叉树T的结点数,结点编号1..n,1≤n≤20000。

第2行,n个整数,空格分隔,表示T的先根序列,序列中结点用编号表示。

第3行,n个整数,空格分隔,表示T的中根序列,序列中结点用编号表示。

第4行,n个整数Wi,空格分隔,表示T中结点的权值,-10000≤Wi≤10000,1≤i≤n。

输出格式:

1行,n个整数,表示根结点到其它所有结点的最短路径长度。

 主要是先根序列,中根序列建树,再dfs递推最短路径就好了。

#include <iostream>
#pragma warning(disable : 4996)
using namespace std;
int xian[20010];
int zhong[20010];
int lef[20010];
int rit[20010];
int hh[20010];
int cost[20010];
void maketree(int d, int s2, int e2) {
	int i = s2;
	while (xian[d] != zhong[i]) {
		i++;
	}
	if (s2 == e2) {
		lef[xian[d]] = rit[xian[d]] = 0;
	}
	else if (i == e2) { rit[xian[d]] = 0;
	lef[xian[d]] = xian[d + 1];
	maketree(d + 1, s2, i - 1);//zuo
	}
	else if (i == s2) {
	lef[xian[d]] = 0;
	rit[xian[d]] = xian[d +1];
	maketree(d +1, i + 1, e2);//you
}
	else {
		rit[xian[d]] = xian[d + i - s2 + 1];
		lef[xian[d]] = xian[d + 1];
		maketree(d + i-s2+1, i + 1, e2);//you
		maketree(d + 1, s2, i - 1);//zuo
	}

}
void bianli(int root) {
	if (!root) return;
	cost[root] += hh[root];
	cost[lef[root]] += cost[root];
	cost[rit[root]] += cost[root];
	bianli(lef[root]);
	bianli(rit[root]);
}
int main()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &xian[i]);
	}
	for (int i = 1; i <= n; i++) {
		scanf("%d", &zhong[i]);
	}
	maketree(1,1,n);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &hh[i]);
	}
	for (int i = 1; i <= n; i++) {
		cost[i] = 0;
	}
	int root = xian[1];
	bianli(root);
	for (int i = 1; i < n; i++)
		printf("%d ", cost[i]);
	printf("%d", cost[n]);
}

/*
6
5 6 3 2 4 1
3 6 5 2 4 1
1 1 1 1 1 1


*/

 

 

7-4 方案计数 (100 分)

组装一个产品需要 n 个零件。生产每个零件都需花费一定的时间。零件的生产可以并行进行。有些零件的生产有先后关系,只有一个零件的之前的所有零件都生产完毕,才能开始生产这个零件。如何合理安排工序,才能在最少的时间内完成所有零件的生产。在保证最少时间情况下,关键方案有多少种,关键方案是指从生产开始时间到结束时间的一个零件生产序列,序列中相邻两个零件的关系属于事先给出的零件间先后关系的集合,序列中的每一个零件的生产都不能延期。

输入格式:

第1行,2个整数n和m,用空格分隔,分别表示零件数和关系数,零件编号1..n,1≤n≤10000, 0≤m≤100000 。

第2行,n个整数Ti,用空格分隔,表示零件i的生产时间,1≤i≤n,1≤Ti≤100 。

第3到m+2行,每行两个整数i和j,用空格分隔,表示零件i要在零件j之前生产。

输出格式:

第1行,1个整数,完成生产的最少时间。

第2行,1个整数,关键方案数,最多100位。

如果生产不能完成,只输出1行,包含1个整数0.

致命的aov拓扑排序,完全不会 

1.首先要用高精度来算路径数

2.可以设置虚源点虚汇点,再转aoe(通法)

3.到关键活动a的关键路径数计算用递归思想实现

即到a的关键路径上的上游(上一个点/一些点)的关键活动b,c,d...的关键路径和就是a的

显然源点的关键路径为1。就递归好了。

最后用一个类似虚圆点的来统计便可。

心得:不用怕树和图,遍历操作后思考要存下什么信息可以帮助解题,递归的思想很重要,要学会从答案/中间任一点找到适合代码表示的同法(大不了就用空间换时间)

#include <iostream>
#include<vector>
#include<queue>
#include<string.h>
#pragma warning(disable : 4996)
using namespace std;
struct bigg {
	int num[105];
	int len;
	void output() {

		if (len == 0) {
			printf("0");
		}
		else {
			for (int i = len - 1; i >= 0; i--) {
				printf("%d", num[i]);
			}
		}
	}
	bigg() {
		memset(num, 0, sizeof(num));
	}
};
bigg& operator +=(bigg& A, bigg& B) {//+= reload
	A.len = max(A.len, B.len);
	for (int i = 0; i < A.len; i++) {
		A.num[i] += B.num[i];
		A.num[i + 1] += A.num[i] / 10;
		A.num[i] %= 10;
	}
	if (A.num[A.len] != 0) {
		A.len++;
	}
	return A;
}
bool operator>=(bigg& A, bigg& B) {
	if (A.len != B.len) return A.len > B.len;
	for (int i = A.len - 1; i >= 0; i--) {
		if (A.num[i] != B.num[i]) {
			return A.num[i] > B.num[i];
		}
	}
	return 1;
}
//struct edge{
//	int a;
//	int b;
//} ed[10010];
struct vertex {
	int du;
	vector<int> head;
	int cost;
	bigg road_sum;
	int eal;
	int vis;
} ver[10010];
queue<int> dudui;
int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", &ver[i].cost);
	}
	for (int i = 1; i <= m; i++) {
		int a, b;
		scanf("%d%d", &a, &b);
		ver[a].head.push_back(b);
		ver[b].du++;
	}
	for (int i = 1; i <= n; i++) {
		if (!ver[i].du) { dudui.push(i);
		ver[i].road_sum.num[0] = 1;
		ver[i].road_sum.len++;
		}
	}
	int top=dudui.size();
	for (int i = 1; i <= n; i++) {
		if (top == 0) {
			printf("0"); return 0;
		}
		int now = dudui.front();
		dudui.pop();
		top--;
		for (vector<int>::iterator it = ver[now].head.begin(); it != ver[now].head.end(); it++) {
			if (ver[now].eal + ver[now].cost > ver[*it].eal)
			{
				ver[*it].eal = ver[now].eal + ver[now].cost;
				ver[*it].road_sum = ver[now].road_sum;
			}
			else if (ver[now].eal + ver[now].cost == ver[*it].eal) {
				ver[*it].road_sum += ver[now].road_sum;
			}
				if (!--ver[*it].du&&!ver[*it].vis) {
					dudui.push(*it);
					top++;
					ver[*it].vis++;
			}
		}
	}
	int maxcost = 0;
	bigg maxroad;
	for (int i = 1; i <= n; i++) {
		if (ver[i].eal + ver[i].cost > maxcost) {
			maxcost = ver[i].eal + ver[i].cost;
			maxroad = ver[i].road_sum;
		}
		else if (ver[i].eal + ver[i].cost == maxcost) {
			maxroad += ver[i].road_sum;
		}
	}
	printf("%d\n", maxcost);
	maxroad.output();
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一次实验: 题目1 单链表相关算法的实验验证。 [实验目的] 验证单链表及其上的基本操作。 [实验内容及要求] 1、 定义单链表类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建单链表; 2)插入操作:别在当前结点后、表头、表尾插入值为x的结点; 3)删除操作:别删除表头结点、表尾结点和当前结点的后继结点; 4)存取操作:别存取当前结点的值和单链表中第k个结点的值; 5)查找操作:查找值为x的元素在单链表中的位置(下标)。 题目2 别给出堆栈、队列相关算法的实验验证。 [实验目的] 验证堆栈、队列及其上的基本操作。 [实验内容及要求](以队列为例) 1、 定义队列类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建队列; 2)插入操作:向队尾插入值为x的元素; 3)删除操作:删除队首元素; 4)存取操作:读取队首元素。 第二次实验 题目1 二叉树相关算法的实验验证。 [实验目的] 验证二叉树的链接存储结构及其上的基本操作。 [实验内容及要求] 1、 定义链接存储的二叉树类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一棵二叉树,并对其初始化; 2)先根、中根、后根遍历二叉树(递归算法); 3)在二叉树中搜索给定结点的父结点; 4)搜索二叉树中符合数据域条件的结点; 5)从二叉树中删除给定结点及其左右子树。 题目2 树和森林的遍历算法的实验验证。 [实验目的] 验证树和森林的遍历算法。 [实验内容及要求] 1、 定义左儿子—右兄弟链接存储的树类和森林类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建树和森林; 2)树和森林的先根遍历的递归和迭代算法; 3)树和森林的后根遍历的递归和迭代算法; 4)树和森林的层次遍历算法。 题目3 二叉查找树的验证实验。 [实验目的] 验证二叉查找树及其相关操作。 [实验内容及要求] 1、 定义二叉查找树的类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)实现二叉查找树结构; 2) 实现二叉查找树的查找、插入和删除等算法; 第三次实验 题目1 邻接表存储的图相关算法的实验验证。 [实验目的] 验证邻接表存的图及其上的基本操作。 [实验内容及要求] 1、 定义邻接表存储的图类。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一个邻接表存储的图; 2)返回图中指定边的权值; 3)返回图中某顶点的第一个邻接顶点; 4)返回图中某顶点关于另一个顶点的下一个邻接顶点的序号; 5)插入操作:向图中插入一个顶点,插入一条边; 6)删除操作:从图中删除一个顶点,删除一条边。 题目2 图的遍历算法的实验验证。 [实验目的] 验证图的遍历算法。 [实验内容及要求] 1、 定义邻接表存储的图。 2、 实验验证如下算法的正确性、各种功能及指标: 1)创建一个图; 2)图的深度优先遍历的递归算法; 3)图的深度优先遍历的迭代算法; 4)图的广度优先遍历算法。 第四次实验 折半插入排序,堆排序,快速排序 请阅读说明文档
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值