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.