AcWing 343. 排序

一种不用Floyd的方法。

时间复杂度

每组 \(O(mn)\)

Description

对于每个输入。
例如 A<B,我们由BA连一条有向边,表示AB小。
通过这样连边,从B出发可以遍历到的所有点都是小于B的,其他字母同理。
于是在每次连边之前,例如 A<B,先判断A在之前的不等式连成的图上能否遍历到B

* 若能,则前后矛盾,输出: "Inconsistency found after t relations.",解决了第二问。
* 若不能,向图中加入此条边,继续。

接着判断是否两两关系确定。
此条件等价于

1. DAG上有且只有一个点的入度为0.
2. topsort一遍后,每个点的深度f[i],互不相同。(f[u]=max(f[v])+1,v 是可直接访问到 u 的点);
3. 不存在f[i]=0,(令入度为0的点的深度为1);

证明:

1. 两两关系确定那肯定只有一个最大的点 <------> 入度为0.
2. 没有相等的点 <----> 每个点的深度f[i],互不相同.
3. 不存在没有关系中的点 <------> 不存在f[i]=0.

如果确定,f[i] 即为 char(i+'A'-1) 输出时的位置。
输出。
不确定就继续。
直到关系加完了,还没确定,那就不确定。

C++ 代码

#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
const int N=36,M=10000+5;
vector<int> v[N];
bool vis[N];
int dep[N];
void dfs(int x)
{
	int i,y;
	vis[x]=true;
	for(i=0;i<(int)v[x].size();i++) {
		y=v[x][i];
		if(!vis[y]) 
			dfs(y);
	}
	return;
}
queue<int> q;
int f[N],d[N];
int n,m;
bool topsort()
{
	while(q.size()) q.pop();
	memset(f,0,sizeof f);
	memset(vis,0,sizeof vis);
	memcpy(d,dep,sizeof d);
	int i,x,y;
	for(i=1;i<=n;i++) 
		if(d[i]==0) 
			q.push(i),f[i]=1;
	if(q.size()>=2) return false;
	vis[1]=true;
	while(q.size()) {
		x=q.front(); q.pop();
		for(i=0;i<(int)v[x].size();i++) {
			y=v[x][i];
			f[y]=max(f[y],f[x]+1);
			d[y]--;
			if(d[y]==0) {
				q.push(y);
				if(vis[f[y]]) return false;
				vis[f[y]]=true;
			}
		}
	}
	for(i=1;i<=n;i++) 
		if(f[i]==0) 
			return false;
	return true;
}

int main()
{
//	freopen("1.in","r",stdin);
	int i,j,ii;
	int x,y;
	char ch;
	while(scanf("%d%d",&n,&m)==2) {
		if(n==0&&m==0) break;
		for(i=1;i<=n;i++)
			v[i].clear();
		memset(dep,0,sizeof dep);
		for(i=1;i<=m;i++) {
			cin>>ch; x=ch-'A'+1;
			cin>>ch;
			cin>>ch; y=ch-'A'+1;
			memset(vis,0,sizeof vis);
			dfs(x);
			if(vis[y]) {
				printf("Inconsistency found after %d relations.\n",i);
				break;
			}
			v[y].push_back(x);
			dep[x]++;
			if(topsort()) {
				printf("Sorted sequence determined after %d relations: ",i);
				for(ii=n;ii>=1;ii--) {
					for(j=1;j<=n;j++) {
						if(f[j]==ii) {
							printf("%c",j+'A'-1);
							break;
						}
					}
				}
				printf(".\n");
				break;
			}
		}
		if(i<m+1) 
			for(i++;i<=m;i++) 
				cin>>ch>>ch>>ch;
		else printf("Sorted sequence cannot be determined.\n");
	}
	return 0;
}

注意事项

1. 多组数据,记得清空.
2. 要 memcpy 一个 dep[] 来 topsort ,否则 dep[] 会被修改.
3. 不能一确定就 continue ,还得把本组剩下的无用数据都读入。
posted @ 2020-11-28 21:01  cjlworld  阅读(71)  评论(0编辑  收藏  举报