P1347 排序


思路:
全序关系+拓扑排序
题目实际上是确认是否存在唯一的全序关系
全序关系唯一 ⟺ 拓扑序唯一 ⟺ 每次 拓扑排序的队列中每时每刻最多有一个元素
(1)合法的情况:
“提示:确定 n 个元素的顺序后即可结束程序,可以不用考虑确定顺序之后出现矛盾的情况”
——需要“加边”与“求拓扑序列”同时进行
——每加一条边,就要求对应的拓扑序列
(2)不合法的情况:
——case1:存在环
1.1 长度>=3的有向回路
1.2 长度=2的有向回路(反向边)
——case2:无法确定顺序
加完m条边之后,仍然没有得到唯一的拓扑序/仍然没有触发有环的判断条件,则为无法确定顺序
代码说明
uniq代表unique的含义,表征:
该轮拓扑排序,是否有唯一的拓扑序
indegree数组
统计每一个点的入度.
tmp数组
每次拓扑排序,入度序列都会变化,用tmp数组作为indegree数组变化的替身
数组大小/映射
A~Z:1~26
除了边集数组struct edge中的原始字母用char之外,其余均用int
注意点 输入数据时,建议用cin接收
关键点 uniq的必要性
按照“加边”与“求拓扑序列”同时进行的思路,会有一个问题,比如:

代码:
#include<bits/stdc++.h>
using namespace std;
struct edge{
char u,v;
}e[650];
int n,m,indegree[30];//indegree[i]保存字母i的入度数
vector<int> d[30];//d[i]存字母i出边的终点
char ch1,symbl,ch2;
void toposort()
{
char u1,v1,head;
bool uniq;
int tmp[30];
for(int i=1;i<=m;++i){
queue<int> q;
vector<int> tp;
uniq=true;
u1=e[i].u,v1=e[i].v;
d[u1-'A'+1].push_back(v1-'A'+1);
indegree[v1-'A'+1]++;
for(int k=1;k<=n;++k)
tmp[k]=indegree[k];
for(int k=1;k<=n;++k){
if(tmp[k]==0)
q.push(k);
}
while(!q.empty()){
if(q.size()>1) uniq=false;
head=q.front(); q.pop();
tp.push_back(head);
for(auto tail:d[head]){
if(--tmp[tail]==0)
q.push(tail);
}
}
if(tp.size()<n){//有环
printf("Inconsistency found after %d relations.",i);
return ;
}
if(uniq){//只要有 孤立点/不连通 就不会触发 //只有 连通无回路 含n个元素的全序 才会触发
printf("Sorted sequence determined after %d relations: ",i);
for(int k=0;k<n;++k){
printf("%c",tp[k]+'A'-1);
}
printf(".");
return ;
}
}
printf("Sorted sequence cannot be determined.");
return ;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;++i){
cin>>ch1>>symbl>>ch2;
e[i].u=ch1;
e[i].v=ch2;
}
toposort();
return 0;
}

浙公网安备 33010602011771号