Algoritmo 7-12: classificação topológica do gráfico acíclico direcionado

descrição do tópico

Obter uma ordem total em um conjunto a partir de uma ordem parcial nesse conjunto é chamado de ordenação topológica. As definições de ordem parcial e ordem total são as seguintes:
Se a relação R no conjunto X é reflexiva, antisimétrica e transitiva, então R é dito ser uma relação de ordem parcial no conjunto X.
Seja R uma ordem parcial no conjunto X, se para cada x, y∈X deve haver xRy ou yRx, então R é dito ser uma ordem total no conjunto X.
A operação de obtenção de ordem topológica pela definição de ordem parcial é a classificação topológica.
O processo de classificação topológica é o seguinte:
1. Selecione um vértice sem predecessor no gráfico direcionado e imprima-o;
2. Exclua do gráfico o vértice e todos os arcos que partem dele.
Repita as duas etapas acima até que todos os vértices tenham sido gerados ou não haja vértices sem predecessores no grafo atual. O último caso indica que há um ciclo no grafo direcionado.
A lista de adjacências é utilizada para armazenar o grafo direcionado, e a pilha é utilizada para armazenar temporariamente todos os vértices com grau de entrada zero. O algoritmo de ordenação topológica pode ser descrito da seguinte forma:
Nesta questão, leia em uma matriz de adjacência de um grafo direcionado (ou seja, uma representação de matriz), construa um grafo direcionado e julgue se o grafo tem um loop de acordo com o algoritmo descrito acima e imprima uma sequência de vértices ordenada topologicamente se houver não é loop.

digitar

A primeira linha de entrada contém um inteiro positivo n, indicando que existem n vértices no grafo. onde n não excede 50.
Cada uma das próximas n linhas tem n inteiros 0 ou 1 separados por espaços. Para o j-ésimo inteiro na i-ésima linha, se for 1, significa que o i-ésimo vértice tem uma aresta direcionada apontando para o j -th vertex , 0 significa que não há aresta direcionada de i para j. Quando i e j são iguais, o número inteiro correspondente é garantido como 0.

saída

Se a leitura do gráfico direcionado contiver ciclos, imprima "ERROR" sem aspas.
Se o gráfico direcionado de leitura não contiver loops, siga o algoritmo na descrição do tópico para gerar a sequência ordenada topologicamente do gráfico por vez e gerar um espaço após cada número inteiro.
Observe a saída de nova linha no final da linha.

#include <iostream>
#include <iomanip>
using namespace std;
  
#define Max 1000
#define MVNum 100         //最大顶点数
#define OK 1
#define ERROR 0
#define OVERFLOW - 2
#define MAXSIZE  10 //顺序栈存储空间的初始分配量
typedef int Status;
typedef int SElemType;
  
typedef int VerTexType; //顶点信息
typedef int OtherInfo;    //和边相关的信息
typedef int ArcType;
  
//- - - - -图的邻接表存储表示- - - - -
typedef struct {
   VerTexType vexs[MVNum];            //顶点表
   ArcType arcs[MVNum][MVNum];      //邻接矩阵
   int vexnum, arcnum;                //图的当前点数和边数
} Graph;
  
typedef struct {
   SElemType *base;//栈底指针
   SElemType *top;//栈顶指针
   int stacksize;//栈可用的最大容量
} SqStack;
  
//算法3.1 顺序栈的初始化
Status InitStack(SqStack &s)
{
   //构造一个空栈S
   s.base = new SElemType[MAXSIZE];//为顺序栈动态分配一个最大容量为MAXSIZE的数组空间
   if(!s.base)
      exit(OVERFLOW); //存储分配失败
   s.top = s.base; //top初始为base,空栈
   s.stacksize = MAXSIZE; //stacksize置为栈的最大容量MAXSIZE
   return OK;
}
 
Status Push(SqStack &s, SElemType e)
{
   /****在此下面完成代码***************/
    if(s.top-s.base==s.stacksize)return ERROR;
    *s.top=e;
    s.top++;
    return OK;
  
   /***********************************/
}
  
//算法3.3 顺序栈的出栈
Status Pop(SqStack &s, SElemType &e)
{
    /****在此下面完成代码***************/
    if(s.base==s.top)return ERROR;
    s.top--;
    e=*s.top;
    return OK;
   /***********************************/
}
 
bool StackEmpty(SqStack S)
{
    /****在此下面完成代码***************/
    if(S.top==S.base)return true;
    else return false;
  
   /***********************************/
}
 
void CreateUDG(Graph &g)
{
   //采用邻接矩阵表示法,创建无向图G
   /****在此下面完成代码***************/
    int i,j;
    cin>>g.vexnum;
    for(i=0;i<g.vexnum;i++)
    {
        for(j=0;j<g.vexnum;j++)
        {
            cin>>g.arcs[i][j];
        }
    }
   /***********************************/
}//CreateUDN
 
  
Status TopSort(Graph g,int topo[])
{
    int i,j,k,m=0,indegree[g.vexnum];
    SqStack s;
    InitStack(s);
    for(i=0;i<g.vexnum;i++)
        indegree[i]=0;
    for(i=0;i<g.vexnum;i++)
    {
        for(j=0;j<g.vexnum;j++)
        {
            indegree[i]=indegree[i]+g.arcs[j][i];
        }
    }
    for(i=0;i<g.vexnum;i++)
    {
        if(!indegree[i])
        {
            g.arcs[i][i]=1;
            Push(s,i);
        }
    }
    while(!StackEmpty(s))
    {
        Pop(s,i);
        topo[m++]=i;
        for(j=0;j<g.vexnum;j++)
        {
            if(g.arcs[i][j]!=0&&i!=j)
            {
                g.arcs[i][j]=0;indegree[j]--;
            }
            if(g.arcs[j][j]==0&&indegree[j]==0)
            {
                g.arcs[j][j]=1;
                Push(s,j);
            }
        }
    }
    if(m<g.vexnum)
    {
        cout<<"ERROR";return 0;
    }else
    {
        for(i=0;i<g.vexnum;i++)
        {
            cout<<topo[i]<<" ";
        }
        return 1;
    }
}
  
int main()
{
   Graph g;
   CreateUDG(g);
   int topo[g.vexnum];
   TopSort(g,topo);
   return 0;
}//main

Exemplo de entrada Copiar

4 
0 1 0 0 
0 
0 1 0 0 0 0 
0 0 0 1 0

Saída de amostra Copiar

3 0 1 2

dica

Nesta questão, é necessário executar a classificação topológica estritamente de acordo com o algoritmo na descrição do título e armazenar os vértices em sequência durante o processo de classificação, e a saída não pode ser executada até que seja finalmente determinado que o grafo direcionado não contém uma volta.
Além disso, para evitar a detecção repetida de vértices com grau de entrada zero, uma estrutura de pilha pode ser usada para manter os vértices com grau de entrada zero no processo de processamento atual.

Acho que você gosta

Origin blog.csdn.net/qq_63306482/article/details/124867777
Recomendado
Clasificación