头像

欢迎来到我的博客

分享题解与总结

P1347 排序

image
image

思路:

全序关系+拓扑排序

题目实际上是确认是否存在唯一的全序关系

全序关系唯一 ⟺ 拓扑序唯一 ⟺ 每次 拓扑排序的队列中每时每刻最多有一个元素

(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的必要性

按照“加边”与“求拓扑序列”同时进行的思路,会有一个问题,比如:

image

代码:

#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;
} 
posted @ 2026-02-13 20:30  king_steph1209  阅读(13)  评论(0)    收藏  举报