- 题333.floyd扩展之求传递闭包-acwing-Q343--排序
- 一、题目
- 二、题解
题333.floyd扩展之求传递闭包-acwing-Q343–排序
一、题目
本题要你求n个字母关系的确定情况,关键在于如何判断出现关系矛盾与所有字母关系全部确定。
首先,易知,本题给定小于关系,其中具有传递性,所以本质是在求传递闭包。因此每次加入新的关系后,判断前先跑一遍floyd求当前传递闭包,若dist[i][j]=1则有’A’+i<‘A’+j。
其次,关于判断有没有出现关系矛盾,只要看dist[i][i]是否为1,如果为1,则i 代码如下:
#includeusing namespace std; const int maxn=26; int n,m; int G[maxn][maxn],dist[maxn][maxn];//G[i][j]=1表示'A'+i与'A'+j直接具备<关系,dist[i][j]=1表示'A'+i<'A'+j int vis[maxn]; void floyd()//求传递闭包 { memcpy(dist,G,sizeof dist);//先将dist初始化成G for(int k=0;k for(int i=0;i for(int j=0;j dist[i][j]=dist[i][j]||dist[i][k]&&dist[k][j];//若i通过k与j连通或i与j已经连通,则将dist[i][j]赋值为1 } } } } int check() { for(int i=0;i if(dist[i][i]) { return -1; } } for(int i=0;i for(int j=0;j if(!dist[i][j]&&!dist[j][i])//若i,j和j,i都不存在<的关系,则说明当前没有将n个字母的关系确定,则直接return 0 { return 0; } } } return 1; } char getNowMin()//得到当前关系处于最小的字母 { for(int i=0;i if(!vis[i])//当前字母没有被输出过 { int j; for(j=0;j if(!vis[j]&&dist[j][i])//如果存在一个没有输出的字母'A'+j比'A'+i的关系更小,则'A'+i不是当前最小 { break; } } if(j==n)//坚持到了最后,没有一个字母'A'+j的关系比'A'+i更小 { vis[i]=1; return 'A'+i; } } } } int main() { while(cin>>n>>m,n||m) { int flag=0,cnt;//flag为0表示还未确定n个字母的关系,为-1表示矛盾,为1表示n个字母关系已经确定 memset(G,0,sizeof G); for(int i=1;i<=m;i++) { string relation; cin>>relation; int u=relation[0]-'A',v=relation[2]-'A'; if(!flag) { G[u][v]=1; floyd(); flag=check(); if(flag) { cnt=i; } } } if(flag==-1) { printf("Inconsistency found after %d relations.n",cnt); } else if(flag==0) { printf("Sorted sequence cannot be determined.n"); } else { memset(vis,0,sizeof vis);//记得把表示是否已经输出过该字母的数组初始化为0 printf("Sorted sequence determined after %d relations: ",cnt); for(int i=0;i printf("%c",getNowMin()); } printf(".n"); } } }
关于floyd求某关系的传递闭包,dist[i][j]表示具有i到j的关系,开始时dist用G直接关系矩阵初始化。代码板子如下:
void floyd()//求传递闭包
{
memcpy(dist,G,sizeof dist);//先将dist初始化成G
for(int k=0;k
for(int i=0;i
for(int j=0;j
dist[i][j]=dist[i][j]||dist[i][k]&&dist[k][j];//若i通过k与j连通或i与j已经连通,则将dist[i][j]赋值为1
}
}
}
}



