图论——拓扑排序
Posted 牧空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论——拓扑排序相关的知识,希望对你有一定的参考价值。
问题描述
设一个有向无环图(DAG),图中有多条有向边 ( U , V ) (U,V) (U,V)。将图中所有的顶点排成一个线性序列,使得在该序列中顶点 U U U都排列在顶点 V V V之前。满足该要求的顶点序列,被称为满足拓扑序列,该过程成为拓扑排序
方法
- 从DAG图中选择入度为0的顶点,并输出
- 从图中删除该入度为0的顶点及所有以它为起点的边
- 重复1和2直到当前图为空,或者图中不存在入度为0的顶点。前者输出的序列为拓扑序列,后者说明图中存在环,没有拓扑序列
例题
题目描述
有 N N N个比赛队 ( 1 ≤ N ≤ 500 ) (1\\le N \\le 500) (1≤N≤500),依次以编号1,2,3…,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即 P 1 P_1 P1赢 P 2 P_2 P2,用 P 1 , P 2 P_1,P_2 P1,P2表示,排名时 P 1 P_1 P1在 P 2 P_2 P2之前。现在请你编写程序确定排名。
输入
输入有若干组,每组中的第一行为两个数N ( 1 ≤ N ≤ 500 ) (1\\le N \\le 500) (1≤N≤500)和M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数 P 1 , P 2 P_1,P_2 P1,P2,表示 P 1 P_1 P1队赢了 P 2 P_2 P2队。
输出
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN = 50;
vector<int> graph[MAXN];
int inDegree[MAXN];
vector<int> ToplogicalSort(int n)
{
vector<int> topology;
//此处使用优先队列为了满足小序号优先输出的条件
priority_queue<int, vector<int>, greater<int>> node;
//先将所有入度为零的节点入队
for (int i = 1; i <= n; i++)
{
if (inDegree[i] == 0)
{
node.push(i);
}
}
while (!node.empty())
{
// 输出队首,删除节点
int u = node.top();
node.pop();
topology.push_back(u);
//遍历该节点所指向的其他节点,
for (int i = 0; i < graph[u].size(); i++)
{
int v = graph[u][i];
//减少入度即除边
inDegree[v]--;
//如果该节点的入度为0,则加入队列
if (inDegree[v] == 0)
node.push(v);
}
}
return topology;
}
int main(int argc, char const *argv[])
{
int n, m;
while (scanf("%d%d", &n, &m) != EOF)
{
memset(graph, 0, sizeof(graph));
memset(inDegree, 0, sizeof(inDegree));
while (m--)
{
int from, to;
scanf("%d%d", &from, &to);
graph[from].push_back(to);
inDegree[to]++;
}
vector<int> answer = ToplogicalSort(n);
for (int i = 0; i < answer.size(); i++)
{
if (i == 0)
printf("%d", answer[i]);
else
printf(" %d", answer[i]);
}
}
return 0;
}
以上是关于图论——拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章