数据结构之图的应用

目录

6-1 实验四图的基本操作-拓扑排序

函数接口定义:

裁判测试程序样例:

输入样例:

输出样例:

7-1 列出连通集

输入格式:

输出格式:

输入样例:

输出样例:

7-2 公路村村通

输入格式:

输出格式:

输入样例:

输出样例:


6-1 实验四图的基本操作-拓扑排序

分数 30

全屏浏览题目

切换布局

作者 daxuejsj

单位 安阳工学院

实验四 图的基本操作-拓扑排序。1、要求学生理解和掌握图的基本概念;2、要求学生深刻理解图的主要的存储结构;3、掌握在邻接表存储结构下的图的深度优先遍历、广度优先遍历;4、掌握图的拓扑排序算法。本题要求根据程序中的图实现一个拓扑排序函数,无输入,直接输出拓扑排序结果,例如:A B C D E F (拓扑排序顶点序列,中间用两个空格间隔)。

函数接口定义:

 

在这里描述函数接口。例如: void TopologicalSort(PGraph g)

裁判测试程序样例:

 

在这里给出函数被调用进行测试的例子。例如: #include<stdio.h> #define MAX_VERTEX_NUM 20 typedef struct { int vertexNum; char vertex[MAX_VERTEX_NUM]; int arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; }Graph,*PGraph; void createdGraph(PGraph g) { int i,j; g->vertexNum=6; for(i=0;i<g->vertexNum;i++) g->vertex[i]='A'+i; for(i=0;i<g->vertexNum;i++) for(j=0;j<g->vertexNum;j++) g->arc[i][j]=0; g->arc[0][1]=1; g->arc[0][2]=1; g->arc[0][3]=1; g->arc[1][4]=1; g->arc[2][1]=1; g->arc[2][4]=1; g->arc[4][3]=1; g->arc[4][5]=1; } /* 请在这里填写答案 */ int main() { Graph graph; createdGraph(&graph); TopologicalSort(&graph); }

输入样例:

无输入

 

输出样例:

在这里给出相应的输出。例如:

A  B  C  D  E  F  
void TopologicalSort(PGraph g){
	int indegree[100];
	for(int i=0;i<=100;i++)   //初始化奥 
		indegree[i]=0;
	for(int i=0;i<g->vertexNum;i++){
		for(int j=0;j<g->vertexNum;j++){
			if(g->arc[i][j]==1)   //计算入度 
				indegree[j]++;
		}
	}
	for(int k=0; k<g->vertexNum; k++){   //这边是遍历节点数遍,时间复杂度高(三重循环)
	                                //如果不嫌麻烦可以用队列方式进行排序 
		for(int i=0; i<g->vertexNum; i++){
			if(indegree[i]==0){
				printf("%c  ",g->vertex[i]);
				for(int j=0; j<g->vertexNum; j++){
					if(g->arc[i][j]==1){     //更新节点入度 
						g->arc[i][j]=0;
						indegree[j]--;
					}
				}
				indegree[i]=-1;//防止重复调用 
				break;
			}
		}
	}
}

7-1 列出连通集

分数 30

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

给定一个有N个顶点和E条边的无向图,请用DFS和BFS分别列出其所有的连通集。假设顶点从0到N−1编号。进行搜索时,假设我们总是从编号最小的顶点出发,按编号递增的顺序访问邻接点。

输入格式:

输入第1行给出2个整数N(0<N≤10)和E,分别是图的顶点数和边数。随后E行,每行给出一条边的两个端点。每行中的数字之间用1空格分隔。

输出格式:

按照"{ v1​ v2​ ... vk​ }"的格式,每行输出一个连通集。先输出DFS的结果,再输出BFS的结果。

输入样例:

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

输出样例:

{ 0 1 4 2 7 }
{ 3 5 }
{ 6 }
{ 0 1 2 7 4 }
{ 3 5 }
{ 6 }
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct GNode *PtrToGNode;
struct GNode{
    int Nv;  //顶点数 
    int Ne;  //边数 
    int G[10][10]; //邻接矩阵
};

typedef PtrToGNode MGraph;

int Visited[10]; //顶点的访问标记 
struct QNode{        //队列定义,后面采用队列进行广搜 
	int Data[10];
	int front;
	int rear;
};

typedef struct QNode* Queue;

int Isempty(Queue Q){    //判断队列是否为空 
	if(Q->front==Q->rear)
	return 1;
	return 0;
}

void add(Queue Q,int a){     //往队列中添加元素 
	Q->rear=(Q->rear+1)%10;
	Q->Data[Q->rear]=a;
}

int put(Queue Q){            //出队列 
	Q->front=(Q->front+1)%10;
	return Q->Data[Q->front];
}

Queue CreatQ(){   //队列创建 
	Queue Q=(Queue)malloc(sizeof(struct QNode));
	Q->front=0;
	Q->rear=0;
	return Q;
}

MGraph Create(){   //图创建 
	MGraph g=(MGraph)malloc(sizeof(struct GNode));
	g->Ne=0;
	g->Nv=0;
	int i,j;
	for(i=0;i<10;i++){   //初始化 
		Visited[i]=0;
		for(j=0;j<10;j++){
			g->G[i][j]=0;
		}
	}
	return g;
}

void Visit(int a){
    printf(" %d",a);   //访问该点 
}

void Insert(MGraph Graph,int a,int b){  //添加元素 
	Graph->G[a][b]=1;
	Graph->G[b][a]=1;
}

void reset(MGraph Graph){    //回溯,重新初始化visited
	int i;
	for(i=0;i<Graph->Nv;i++){
		Visited[i]=0;
	}
}

int Isask(int a){   //该点是否被访问 
	if(Visited[a]==0)
	return 0;
	return 1;
}

void DFS(MGraph Graph, int V){    //深搜 
		Visit(V);
		Visited[V]=1;
		int i;
		for(i=0;i<Graph->Nv;i++){
			if(Graph->G[V][i]==1&&Visited[i]==0){
				DFS(Graph,i);
			}
		}
}

void BFS( MGraph Graph, int V){  //广搜 
		Queue Q=CreatQ();
		Visit(V);
		Visited[V]=1;
		int v,w;
		add(Q,V);
		while(!Isempty(Q)){
			v=put(Q);
			for(w=0;w<Graph->Nv;w++){
				if(Visited[w]==0&&Graph->G[v][w]==1){
					Visit(w);
					Visited[w]=1;
					add(Q,w);
				}
			}
		}
}

int main(){
	int n,e;
	scanf("%d %d",&n,&e);
	int i,j,a,b;
	MGraph Graph=Create();
	Graph->Nv=n;
	Graph->Ne=e;
	for(i=0;i<e;i++){
		scanf("%d %d",&a,&b);
		Insert(Graph,a,b);
	}
	for(i=0;i<n;i++){
		if(!Isask(i)){
			printf("{");
			DFS(Graph,i);
			printf(" }\n");
		}
	}
	reset(Graph);
	for(i=0;i<n;i++){
		if(!Isask(i)){
			printf("{");
			BFS(Graph,i);
			printf(" }\n");
		}
	}
	return 0;
}

7-2 公路村村通

分数 40

全屏浏览题目

切换布局

作者 陈越

单位 浙江大学

现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本。

输入格式:

输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N);随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本。为简单起见,城镇从1到N编号。

输出格式:

输出村村通需要的最低成本。如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路。

输入样例:

6 15
1 2 5
1 3 3
1 4 7
1 5 4
1 6 2
2 3 4
2 4 6
2 5 2
2 6 6
3 4 6
3 5 1
3 6 1
4 5 10
4 6 8
5 6 3

输出样例:

12

#include<stdio.h>
typedef struct {
	int b;
	int e;
	int weight;
}Edge;
Edge edge[10000];
void sortEdge(Edge *edge,int M)
{
	Edge temp;
	for (int i = 0; i < M; i++)
	{
		for (int j = i + 1; j < M; j++)
		{
			if (edge[i].weight > edge[j].weight)
			{
				temp = edge[i];
				edge[i] = edge[j];
				edge[j] = temp;
			}
		}
	}
 
}
int find_parent(int *parent, int f)
{
	while (parent[f] > 0)
	{
		f = parent[f];
	}
	return f;
}
 
int Kruskal(Edge* edge,int N, int M)
{
	int parent[10000];
	int NumEdges = 0;//初始化选中的边数
	int MinLength = 0;//初始化最短路径长度
	for (int i = 1; i < N+1; i++)
	{//初始化数组为1
		parent[i] = 0;
	}
	for (int i = 0; i < M; i++)
	{
		int n = find_parent(parent, edge[i].b);
		int m = find_parent(parent, edge[i].e);
		if (NumEdges == N-1)
			break;
		if (n != m)
		{
			parent[n] = m;
			NumEdges++;
			MinLength += edge[i].weight;
		}
 
	}
	if (NumEdges == N-1)
		return MinLength;
	else
		return -1;
 
}
 
int main()
{
	int N, M;//城镇数目和候选道路数目
	 scanf("%d %d",&N,&M);
	for (int i = 0; i < M; i++)
	{
		scanf("%d %d %d",&edge[i].b,&edge[i].e,&edge[i].weight);
	}
	sortEdge(edge, M);
	printf("%d", Kruskal(edge, N, M));
	return 0;
}
 

 这道题采用的是(Kruskal)算法,这边也可以用(Prim)算法,请大家自己尝试

kbddkykyzzl,especially cyk

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值