AcWing 343. 排序
一种不用Floyd
的方法。
时间复杂度
每组 \(O(mn)\)
Description
对于每个输入。
例如 A<B
,我们由B
向A
连一条有向边,表示A
比B
小。
通过这样连边,从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 ,还得把本组剩下的无用数据都读入。