数据结构实验三 2024_树与图实验

数据结构实验三 2024_树与图实验

7-1 根据后序和中序遍历输出前序遍历

本题要求根据给定的一棵二叉树的后序遍历和中序遍历结果,输出该树的前序遍历结果。

输入格式:

第一行给出正整数 n (≤30),是树中结点的个数。随后两行,每行给出 n 个整数,分别对应后序遍历和中序遍历结果,数字间以空格分隔。题目保证输入正确对应一棵二叉树。

输出格式:

在一行中输出Preorder: 以及该树的前序遍历结果。数字间有1个空格,行末不得有多余空格。

输入样例:

7
2 3 1 5 7 6 4
1 2 3 4 5 6 7

输出样例:

Preorder: 4 1 3 2 6 5 7

题目分析

  • 根据中序遍历和后序遍历的得到前序遍历的方法为,每次通过后序遍历找到根节点,然后递归左右子树,递归的方法为,在中序遍历中计算出左子树和右子树的大小,然后在后序遍历中确定左右子树序列范围
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int n,tot=0;
int a[50],b[50],ans[50];
int find(int l,int r,int x){
	for(int i=l;i<=r;i++){
		if(a[i]==x) return i;
	}
	return 0;
}
void dfs(int l1,int r1,int l2,int r2){
	int rt=b[r2];//b[r2]为根节点
	int id=find(l1,r1,rt);
	ans[++tot]=rt;
	if(id==0) return;
	if(id>l1) dfs(l1,id-1,l2,r2-r1+id-1);
	if(id<r1) dfs(id+1,r1,l2+id-l1,r2-1);
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<=n;i++) cin>>a[i];
	dfs(1,n,1,n);
	cout<<"Preorder: ";
	for(int i=1;i<=n;i++) cout<<ans[i]<<" "[i==n];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

7-2 完全二叉树的层序遍历

一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是完美二叉树。对于深度为 D 的,有 N 个结点的二叉树,若其结点对应于相同深度完美二叉树的层序遍历的前 N 个结点,这样的树就是完全二叉树

给定一棵完全二叉树的后序遍历,请你给出这棵树的层序遍历结果。

输入格式:

输入在第一行中给出正整数 N(≤30),即树中结点个数。第二行给出后序遍历序列,为 N 个不超过 100 的正整数。同一行中所有数字都以空格分隔。

输出格式:

在一行中输出该树的层序遍历序列。所有数字都以 1 个空格分隔,行首尾不得有多余空格。

输入样例:

8
91 71 2 34 10 15 55 18

输出样例:

18 34 55 71 2 10 15 91

题目分析

  • 由于是完全二叉树,根据完全二叉树的性质可以知道,在层序遍历中,若i为当前子树根节点,则2i为左孩子节点,2i+1为右孩子节点,代码中用u<<1 与 u<<1|1表示左右孩子
  • 那么可以模拟后序遍历的顺序,计算出层序遍历的答案
#include<bits/stdc++.h>
#define endl '\n'
#define lc u<<1
#define rc u<<1|1
using namespace std;
int n,tot=1;
int a[50],ans[50];
void dfs(int u){
	if(u>n) return;
	dfs(lc);
	dfs(rc);
	ans[u]=a[tot];
	tot++;
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	dfs(1);
	for(int i=1;i<=n;i++) cout<<ans[i]<<" "[i==n];
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

7-3 最短工期

一个项目由若干个任务组成,任务之间有先后依赖顺序。项目经理需要设置一系列里程碑,在每个里程碑节点处检查任务的完成情况,并启动后续的任务。现给定一个项目中各个任务之间的关系,请你计算出这个项目的最早完工时间。

输入格式:

首先第一行给出两个正整数:项目里程碑的数量 N(≤100)和任务总数 M。这里的里程碑从 0 到 N−1 编号。随后 M 行,每行给出一项任务的描述,格式为“任务起始里程碑 任务结束里程碑 工作时长”,三个数字均为非负整数,以空格分隔。

输出格式:

如果整个项目的安排是合理可行的,在一行中输出最早完工时间;否则输出"Impossible"。

输入样例 1:

9 12
0 1 6
0 2 4
0 3 5
1 4 1
2 4 1
3 5 2
5 4 0
4 6 9
4 7 7
5 7 4
6 8 2
7 8 4

输出样例 1:

18

输入样例 2:

4 5
0 1 1
0 2 2
2 1 3
1 3 4
3 2 5

输出样例 2:

Impossible

题目分析

  • 拓扑排序,每次取出入度为0的点,删除该点与所有与该点相连的边,(即所有与其相连的点入度-1),然后其相连点的答案,这里用f[i]表示到达i点,满足所有前驱已完成时至少需要花费的时间
  • 注意判断无解情况,即判断该有向图是否有环(拓扑拆图之后若还有剩余点则存在环)
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N=110;
struct node{
	int to,w;
};
vector<node> g[N];
int n,m,tot=0;
int ind[N],f[N];
void topo(){
	queue<int> q;
	for(int i=0;i<n;i++){
		if(ind[i]==0){
			tot++;
			q.push(i);
		}
	}
	while(q.size()){
		int u=q.front();
		q.pop();
		for(auto [v,w]:g[u]){
			ind[v]--;
			f[v]=max(f[v],f[u]+w);
			if(ind[v]==0){
				tot++;
				q.push(v);
			}
		}
	}
	
}
void solve(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		int u,v,w;cin>>u>>v>>w;
		g[u].push_back({v,w});
		ind[v]++;
	}
	topo();
	int ans=0;
	if(tot!=n){
		cout<<"Impossible"<<endl;
		return;
	}
	for(int i=0;i<n;i++) ans=max(ans,f[i]);
	cout<<ans<<endl;

}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

7-4 旅游规划

有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

输入格式:

输入说明:输入数据的第 1 行给出 4 个正整数 nmsd,其中 n(2≤n≤500)是城市的个数,顺便假设城市的编号为 0~(n−1);m 是高速公路的条数;s 是出发地的城市编号;d 是目的地的城市编号。随后的 m 行中,每行给出一条高速公路的信息,分别是:城市 1、城市 2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过 500。输入保证解的存在。

输出格式:

在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

输入样例:

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

输出样例:

3 40

题目分析

  • 多权最短路模板,和dij写法基本相同,只需要在运算符重载时判断一下条件优先级即可
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=510;
int n,m,st,ed;
struct node{
	int to,w,c;
	bool operator< (const node rhs)const{
		if(w!=rhs.w) return w>rhs.w;  //大的优先级小
		else return c>rhs.c;
	}
};
vector<node> g[N];
bool vis[N];
int dis[N],cost[N];
void dij(int x){
	priority_queue<node> q;
	dis[x]=0,cost[x]=0;
	q.push({x,0,0});
	while(!q.empty()){
		auto t=q.top();
		q.pop();
		int u=t.to;
		if(vis[u]) continue;
		for(auto tmp:g[u]){
			auto [v,w,c]=tmp;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				cost[v]=cost[u]+c;
				q.push({v,dis[v],cost[v]});
				continue;	
			}
			if(dis[v]==dis[u]+w && cost[v]>cost[u]+c){
				dis[v]=dis[u]+w;
				cost[v]=cost[u]+c;
				q.push({v,dis[v],cost[v]});
			}
		}
	}
}
void init(){
	for(int i=0;i<=n+5;i++){
		dis[i]=cost[i]=1e9;
		vis[i]=0;
	}
}
void solve(){
	cin>>n>>m>>st>>ed;
	init();
	for(int i=1;i<=m;i++){
		int u,v,w,c;cin>>u>>v>>w>>c;
		g[u].push_back({v,w,c});
		g[v].push_back({u,w,c});
	}
	dij(st);
	cout<<dis[ed]<<" "<<cost[ed]<<endl;

}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	int T=1;
	while(T--) solve();
	return 0;
}

posted @ 2024-11-18 13:01  Persona_owl  阅读(26)  评论(0编辑  收藏  举报