13周实验

3.求最小生成树的权值和

【问题描述】
 已知含有n个顶点(编号从1开始)的带权连通无向图,采用邻接矩阵存储,邻接矩阵以三元组的形式给出 (三元组数据结构见教材5.3.2节),只给出不包括主对角线元素在内的下三角这部分的元素,且不包括不邻接的顶点对。请采用Prim算法,求该连通图从1号顶点出发的最小生成树的权值之和。
【输入形式】
 第1行给出图中结点个数n和三元组的个数num,之后每行给出一个三元组,数之间用1个空格隔开。(注意这里顶点的序号是从1到n,而不是0到n-1,程序里要小心!)
【输出形式】
 求解的最小生成树的各条边、各边的权值、最小生成树的权值和
【样例输入】
 5 8
 2 1 7
 3 1 6
 3 2 8
 4 1 9
 4 2 4
 4 3 6
 5 2 4
 5 4 2
【样例输出】

1-3:6
3-4:6
4-5:2
4-2:4
18

【样例说明】
 权值是正整数,可能很大,但不需要考虑整型溢出问题

#include<iostream>
using namespace std;
#define MAX 99999//定义一个值来代表无穷大
#define MAXNUM 100
typedef struct AdjMatrix
{
  int vexnum,arcnum;
  int arcs[MAXNUM][MAXNUM];
}AdjMatrix;
typedef struct a
{
  int adjvex;
  int lowcost;
}closedge;
AdjMatrix g;
void CreateGraph(AdjMatrix &g)
{
  int i,j;
  int a,b,c;
  cin>>g.vexnum>>g.arcnum;
  for(i=1;i<=g.vexnum;i++)
  {
      for(j=1;j<=g.vexnum;j++)
      {
          g.arcs[i][j]=MAX;
      }
  }
  for(i=1;i<=g.arcnum;i++)
   {
     cin>>a>>b>>c;
     g.arcs[a][b]=c;
     g.arcs[b][a]=c;
   }
}
int Minium(closedge c[])//找最小值
{
  int Min=MAX,Mini;
  for(int i=1;i<=g.vexnum;i++)
   {
     if(c[i].lowcost!=0&&c[i].lowcost<Min)
     {
       Min=c[i].lowcost;
       Mini=i;
     }
   }
   return Mini;
}
void MiniSpanTree_Prim(AdjMatrix g,int u=1)//prim算法
{
  int sum=0;
  closedge c[MAXNUM+1];
  c[u].lowcost=0;//u到自己的权值为0
  for(int i=1;i<=g.vexnum;i++)//赋值
   {
     if(i!=u)
      {
        c[i].adjvex=u;
        c[i].lowcost=g.arcs[u][i];
      }
   }
   for(int e=1;e<=g.vexnum-1;e++)
   {
     int v=Minium(c);
     sum+=c[v].lowcost;
     cout<<c[v].adjvex<<"-"<<v<<":"<<c[v].lowcost<<endl;
     c[v].lowcost=0;
     for(int i=1;i<=g.vexnum;i++)
      {
        if(g.arcs[v][i]<c[i].lowcost)
         {
           c[i].lowcost=g.arcs[v][i];
           c[i].adjvex=v;
         }
      }
   }
   cout<<sum<<endl;
}
int main()
{
  CreateGraph(g);
  MiniSpanTree_Prim(g,1);
  return 0;
}

5.拓扑排序

【问题描述】

拓扑排序的流程如下:

1. 在有向图中选一个没有前驱的顶点并且输出之;

2. 从图中删除该顶点和所有以它为尾的弧。

重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后一种情况则说明有向图中存在环。

采用邻接表存储有向图(可参考本次实验第2题代码),并通过栈来暂存所有入度为零的顶点。拓扑排序算法请参考教材上算法7.11和7.12或课件上的相应算法。

在本题中,读入一个有向图的信息(输入形式同本次实验第2题,详见下述【输入形式】),建立有向图并按照上述算法判断此图是否有回路,如果没有回路则输出拓扑有序的顶点数据序列。顶点的数据类型为int型。

注意:顶点编号从0开始。

【输入形式】仿照算法7.2的输入:

第1行输入图的结点个数n。第2行是图的各顶点数据。

之后的若干行(有向图为e行, 无向图为2e行) 依次输入各条边的弧尾、弧头的顶点编号。注意:因为算法7.2是按头插法建边链表的,所以要使得到的每个边链表中 都是按照邻接顶点的编号由小到大的顺序链接存储,就必须输入各边的顺序 首先是按照弧尾编号由小到大的顺序,并且输入弧尾相同的各边时 按照弧头顶点编号由大到小的顺序输入这些边,具体见样例输入。

最后一行输入-1和-1表示输入结束。

【输出形式】

如果读入的有向图含有回路,请输出“ERROR”,不包括引号。

如果读入的有向图不含有回路,请按照题目描述中的算法依次输出图的拓扑有序序列,每个整数后输出一个空格。

请注意行尾输出换行。

【样例输入】
4

0(空格)1(空格)2(空格)3

0(空格)1

1(空格)2

3(空格)2

-1(空格)-1

【样例输出】

3(空格)0(空格)1(空格)2(空格)

【说明】

本题中,需要严格的按照题目描述中的算法进行拓扑排序,并在排序的过程中将顶点数据先依次存储下来,直到最终能够判定有向图中不含回路之后,才能够进行输出,否则不能通过测试数据。

#include<iostream>
#include<stack>
using namespace std;
#define MAXNUM 200
typedef struct ArcNode//边
{
  int adjvex;
  struct ArcNode *nextarc;
}ArcNode;
typedef struct VertexNode//点
{
  int info;
  ArcNode *firstarc;
}VertexNode;
typedef struct//邻接表
{
  VertexNode vertex[MAXNUM];
  int vexnum,arcnum;
}AdjList;
void Create(AdjList &g)//创建邻接表
{
   int x,y;
   g.vexnum=g.arcnum=0;
   cin>>g.vexnum;
   for(int i=0;i<g.vexnum;i++)
   {
       g.vertex[i].firstarc=NULL;
   }
   for(int i=0;i<g.vexnum;i++)
    {
       cin>>g.vertex[i].info;
    }
    while(cin>>x>>y)
    {
        if(x==-1&&y==-1) break;
        ArcNode *p1=NULL;
        p1=new ArcNode;
        p1->adjvex=y;
        p1->nextarc=g.vertex[x].firstarc;
        g.vertex[x].firstarc=p1;
        g.arcnum++;
    }
}
void FindID(AdjList G,int indegree[MAXNUM])//将每个结点的度存入indegree数组中
{
    int i;
    ArcNode *p=NULL;
    for(i=0;i<G.vexnum;i++)
        indegree[i]=0;
    for(i=0;i<G.vexnum;i++)
    {
        p=G.vertex[i].firstarc;
        while(p!=NULL)
        {
            indegree[p->adjvex]++;
            p=p->nextarc;
        }
    }
}
void TopoSort(AdjList G)//拓扑排序
{
    stack<int> S;
    int indegree[MAXNUM];
    int i,Count,k;
    int sorted[100]={0};
    ArcNode *p;
    FindID(G,indegree);
    for(i=0;i<G.vexnum;i++)
    {
        if(indegree[i]==0) S.push(i);
    }
    Count=0;
    while(!S.empty())
    {
        i=S.top();
        S.pop();
        sorted[Count]=G.vertex[i].info;
        Count++;
        p=G.vertex[i].firstarc;
        while(p!=NULL)
        {
            k=p->adjvex;
            indegree[k]--;
            if(indegree[k]==0) S.push(k);
            p=p->nextarc;
        }
    }
    if(Count<G.vexnum) cout<<"ERROR"<<endl;
    else
    {
        for(i=0;i<Count;i++)
        {
            cout<<sorted[i]<<" ";
        }
    }
}
int main()
{
    AdjList g;
    Create(g);
    TopoSort(g);
    return 0;
}
  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值