图(考点+最短路径问题+最小生成树)

图的基本术语

子图:类似于子集;

无向图和有向图:对于无向图若具有n(n-1)/2条边,则称之为无向完全图;对于有向图若具有n(n-1)条弧,则称之为有向完全图;

稀疏图和稠密图:边或弧(e<nlog2n)的图为稀疏图,反之为稠密图;

权和网:边带有权值,这种图叫做网;

邻接点和关联: 邻接是指顶点和顶点之间的关系,关联是指边和顶点之间的关系;

度、入度、出度:顶点v的度指和v相关联的边的数目;对于有向图,入度以v为头的弧的数目,出度以v为尾的弧的数目(<v1,v2>v1为弧尾(箭头指向自己),v2为弧头(箭头指向别人));

路径和路径长度:路径是A->B->...的一条路径,路径长度是一条路径经过的边或弧的数目;

回路或环:第一个顶点和最后一个顶点相同的路径称之为回路或环;

连通、连通图、连通分量(极大连通子图):连通;全连通的图;不可去如何一条边;

图的存储结构

邻接矩阵

//邻接矩阵 

#define Maxint 32767

#define Mvnum 100

typedef struct{

  int vexs[Mvnum];

  int arcs[Mvnum][Mvnum];

  int vexnum,arcnum;
}AG;

//邻接矩阵创建无向图

int Locvex(Ag &G,int v){

  for(int i=0;i<G.vexnum;i++){

    if(G.vexs[i]==v) return i;

  }

  return -1;

}

int createudn(AG &G){

  cin>>G.vexnum>>G.arcnum;

  for(int i=0;i<G.vexnum;i++) cin>>G.vexs[i];

  for(int i=0;i<G.vexnum;i++)

    for(int j=0;j<G.vexnum;j++)

      G.arcs[i][j]=Maxint;

  for(int k=0;k<G.arcnum;k++){

    int v1,v2,w;cin>>v1>>v2>>w;

    int i=locvex(G,v1);int j=locvex(G,v2);

    G.arcs[i][j]=w;

    G.arcs[j][i]=G.arcs[i][j];//删掉为有向图 

  }

}

邻接表

//邻接表

#define Mvnum 100

typedef struct Arcnode{

  int adjvex;

  struct Arcnode *nextarc;

  int info;

}ArcNode;

typedef struct Vnode{

  int data;

  ArcNode *firstarc;

}VNode,AdjList[Mvnum];

typedef struct{

  AdjList vertices;

  int vexnum,arcnum;

}AlGraph;

//邻接表创建无向图 

int create(AlGraph &G){

  cin>>G.vexnum>>G.arcnum;

  for(int i=0;i<G.vexnum;i++){

    cin>>G.vertices[i].data;

    G.vertices[i].firstarc=NULL;
  }

  for(int k=0;k<G.arcnum;i++){

    int v1,v2;cin>>v1>>v2;

    int i=locatevex(G,v1);

    int j=locatevex(G,v2);

    p1=new ArcNode;

    p1->adjvex=j;

    p1->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p1;

    p2=new ArcNode;

    p2->adjvex=i;

    p2->nextarc=G.vertices[j].firstarc;G.vertices[j].firstarc=p2;

  }
  return 1;
} 

最小生成树

普利姆算法

//(最小生成树)普利姆算法
struct{
  int adjvex;
  int lowcoat;
}closedge[Nvnum];
void Minstree_prim(AG &G,int u){
  int k=Locvex(G,u);
  for(int j=0;j<G.vexnum;j++)
    if(j!=k) closedge[j]={u,G.arcs[k][j]};
  closedge[k].lowcoat=0;
  for(int i=1;i<G.vexnum;i++){
    int K=min(closedge);
    int u0=closedge[K].adjvex;
    int v0=G.vexs[k];
    cout<<u0<<"--"<<v0;
    closedge[k].lowcoat=0;
    for(int j=0;j<G.vexnum;j++)
      if(G.arcs[k][j]<closedge[j].lowcoat)
        closedge[j]={G.vexs[K],G.arcs[K][j]}; 
  }
} 

克鲁斯卡尔算法

#include <bits/stdc++.h>
using namespace std;
#define Maxint 32767
#define Mvnum 100
//邻接矩阵 
typedef struct{
  int vexs[Mvnum];
  int arcs[Mvnum][Mvnum];
  int vexnum,arcnum;
}AG;
typedef struct Edge{
  int head;
  int tail;
  int lowcost;
}Edge; 
//邻接矩阵创建无向图
int Locvex(AG &G,int v){
  for(int i=0;i<G.vexnum;i++){
    if(G.vexs[i]==v) return i;
  }
  return -1;
}
int createudn(AG &G,Edge edge[Mvnum]){
  cin>>G.vexnum>>G.arcnum;
  for(int i=0;i<G.vexnum;i++) cin>>G.vexs[i];
  for(int i=0;i<G.vexnum;i++)
    for(int j=0;j<G.vexnum;j++)
      G.arcs[i][j]=Maxint;
  for(int k=0;k<G.arcnum;k++){
    int v1,v2,w;cin>>v1>>v2>>w;
    int i=Locvex(G,v1);int j=Locvex(G,v2);
    G.arcs[i][j]=w;
    G.arcs[j][i]=G.arcs[i][j];//删掉为有向图 
    edge[i].head=v1;
    edge[i].tail=v2;
    edge[i].lowcost=w;
  }
}
//(最小生成树)克鲁斯卡尔算法 
int vexset[Mvnum];
void MinsTree_kruskal(AG G,Edge edge[Mvnum]){
  sort(edge,edge+G.arcnum,[](const Edge &x,const Edge &y){
    return x.lowcost<y.lowcost;
  });
  for(int i=0;i<G.vexnum;i++) vexset[i]=i;
  for(int i=0;i<G.arcnum;i++){
    int v1=Locvex(G,edge[i].head);
    int v2=Locvex(G,edge[i].tail);
    if(vexset[v1]!=vexset[v2]){
      cout<<edge[i].head<<"--"<<edge[i].tail<<" :"<<edge[i].lowcost<<"\n";
      for(int j=0;j<G.vexnum;j++)
        if(vexset[j]==vexset[v2]) vexset[j]=vexset[v1];
    }
  }
}
int main(){
  AG G;
  Edge edge[Mvnum];
  createudn(G,edge);
  MinsTree_kruskal(G,edge);
  return 0;
}

最短路径问题

迪杰斯特拉算法

//(最短路径)迪杰斯特拉算法 
int s[Mvnum],cost[Mvnum],path[Mvnum];
void short_dij(AG &G,int v0){
  int n=G.vexnum;
  for(int v=0;v<n;v++){
    s[v]=0;
    cost[v]=G.arcs[v0][v];
    if(cost[v]<Maxint) path[v]=v0;
    else path[v]=-1;
  }
  s[v0]=1;
  for(int i=1;i<n;i++){
    min=Maxint;
    for(int w=0;w<n;w++)
      if(s[w]==0&&cost[w]<min){
        v=w;min=cost[w];
      }
    s[v]=1;
    for(int w=0;w<n;w++){
      if(s[v]==0&&(cost[v]+G.arcs[v][w]<cost[w])){
        cost[w]=cost[v]+G.arcs[v][w];
        path[w]=v;
      } 
    }
  }
}
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千寻千

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值