洛谷题单指南-图的基本应用-P1347 排序
原题链接:https://www.luogu.com.cn/problem/P1347
题意解读:在给出多对关系字母的比较关系之后,判断能否确定所有字母的顺序。
解题思路:
对字母的关系建立图,如A<B建立A指向B的一条边。
如果在拓扑排序过程中,每次寻找入度为0的点只有一个,且最终可以形成拓扑序,则可以确定所有字母的顺序,拓扑序即是答案;
如果拓扑排序过程中,某次寻找入度为0的点有多个,且正常完成拓扑排序,说明无法确定所有字母的顺序;
如果无法正常完成拓扑排序,说明图中有环,即发现了矛盾。
注意:
1、如果出现自环,即发现了矛盾;
2、如果同时出现多个入度为0、自环,优先输出矛盾,其次是没有顺序。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
vector<int> g[N]; //邻接表
int in[N]; //入度
int n, m;
char u, v, op;
int res;
vector<int> order; //保存顺序
//返回0:无法判断顺序 1:可以判断顺序 2:出现矛盾
int bfs()
{
bool noorder = false;
queue<int> q;
order.resize(0);
int iin[N];
for(int i = 0; i < n; i++) iin[i] = in[i]; //拷贝入度数组
for(int i = 0; i < n; i++)
{
if(iin[i] == 0) q.push(i);
}
if(q.size() > 1) noorder = true; //同时有多个入度是0的节点,无法判断顺序
while(q.size())
{
int u = q.front(); q.pop();
order.push_back(u); //记录顺序
int cnt = 0; //u指向的节点的入度减为0的个数
for(int v : g[u])
{
iin[v]--; //把x指向的节点入度--
if(iin[v] == 0)
{
cnt++;
if(cnt > 1) noorder = true; //同时有多个入度是0的节点,无法判断顺序
q.push(v);
}
}
}
if(order.size() != n) return 2; //先看是否存在矛盾
if(noorder) return 0; //再考虑没有顺序
else return 1; //找到顺序
}
int main()
{
cin >> n >> m;
int i;
for(i = 1; i <= m ;i++)
{
cin >> u >> op >> v;
if(u == v) //出现矛盾,自己小于自己,自环
{
cout << "Inconsistency found after " << i << " relations.";
return 0;
}
g[u - 'A'].push_back(v - 'A');
in[v - 'A']++;
res = bfs();
if(res == 1)
{
cout << "Sorted sequence determined after "<< i << " relations: ";
for(int v : order) cout << (char)(v + 'A');
cout << ".";
return 0;
}
if(res == 2)
{
cout << "Inconsistency found after " << i << " relations.";
return 0;
}
}
if(res == 0) cout << "Sorted sequence cannot be determined.";
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?