题目大意:给你n个大写字母(从A开始往后数n-1个)和m组字母之间的关系(X<Y表示X在Y的前面),让你判断这些字母之间先后关系:
(1)k组关系后(k<=m)若能判断出n个字母之间的先后关系,那么输出这个序列;
(2)k组关系后(k<=m)若判断出有相互矛盾的关系存在,那么输出错误;
(3)m组关系后若仍不能判断n个字母之间的关系,那么就输出否。
分析:很明显的拓扑排序,但我们要先明确这3个输出的优先级:(2)的优先级最高,其次是(1),(3)的优先级最低。原因很简单,首先(1)(2)不一定需要遍历这m组关系,而且我们在找出正确关系的过程中若发现矛盾(即判断出了(2)),那么就不再执行(1)了。
拓扑排序的模板很多,下面我分别用了可达矩阵和STL容器类两种方法:
可达矩阵实现代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int edge[30][30],ind[30];
int seq[30];
int Top_sort(int n)
{
int d[30],dnum,d0;//d[]用来存放当前情况下的顶点入度,dnum表示入度为0的个数,d0表示入度为0的顶点的编号
int cnt=0;
int flag=1;
for(int i=0;i<n;i++)
d[i]=ind[i];
for(int i=0;i<n;i++)
{
dnum=0;
for(int j=0;j<n;j++)
if(d[j]==0)
{
dnum++;
d0=j;
}
if(dnum==0) return -1;
if(dnum>1) flag=0;
seq[cnt++]=d0;
d[d0]=-1;
for(int j=0;j<n;j++)
if(edge[d0][j]) d[j]--;
}
return flag;
}
int main()
{
int m,n;
while(scanf("%d%d",&n,&m))
{
if(m==0&&n==0) break;
char u,c,v;
bool flag=false;
memset(edge,0,sizeof(edge));
memset(ind,0,sizeof(ind));
for(int i=1;i<=m;i++)
{
cin>>u>>c>>v;
if(flag) continue;
u-='A';
v-='A';
edge[u][v]=1;
ind[v]++;
int cnt=Top_sort(n);
if(cnt==1)
{
printf("Sorted sequence determined after %d relations: ",i);
for(int j=0;j<n;j++)
printf("%c",seq[j]+'A');
printf(".\n");
flag=true;
}
if(cnt==-1)
{
printf("Inconsistency found after %d relations.\n",i);
flag=true;
}
}
if(!flag) puts("Sorted sequence cannot be determined.");
}
return 0;
}
用STL中vector容器类和queue的实现代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
vector <int> edge[30];
int indgree[30],seq[30];
int Top_sort(int n)
{
queue<int> que;
int ind[30];
int tmp=0;
bool res=false;
for(int i=0;i<n;i++)
{
ind[i]=indgree[i];
if(ind[i]==0) que.push(i);
}
while(!que.empty())
{
if(que.size()>1) res=true;
int cnt=que.front();
que.pop();
seq[tmp++]=cnt;
for(int i=0;i<edge[cnt].size();i++)
{
ind[edge[cnt][i]]--;
if(ind[edge[cnt][i]]==0) que.push(edge[cnt][i]);
}
}
if(tmp<n) return -1;
if(res) return 0;
return 1;
}
int main()
{
int n,m,i;
char u,c,v;
while(scanf("%d%d",&n,&m))
{
if(n==0&&m==0) break;
memset(indgree,0,sizeof(indgree));
int flag;
bool judge=0;
for(i=0;i<=30;i++)
edge[i].clear();
for(i=1;i<=m;i++)
{
cin>>u>>c>>v;
if(judge) continue;
u-='A';
v-='A';
edge[u].push_back(v);
indgree[v]++;
flag=Top_sort(n);
if(flag==-1)
{
printf("Inconsistency found after %d relations.\n",i);
judge=1;
}
else if(flag==1)
{
printf("Sorted sequence determined after %d relations: ",i);
for(int k=0;k<n;k++)
printf("%c",seq[k]+'A');
printf(".\n");
judge=1;
}
}
if(!judge) puts("Sorted sequence cannot be determined.");
}
return 0;
}