有两题需要用时间。
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();
}