传送门:POJ1094
题意:给出n个字母之间的大小关系(以小于号形式两两给出),判断:
1.该字母序列有序,并依次输出;
2.该序列不能判断是否有序;
3.该序列字母次序之间有矛盾,即有环存在。
看题解才知道是典型拓扑排序,也是我第一次做拓扑排序的题,虽然数据结构学过拓扑排序,但自己并没有做到活学活用啊!看了别人的代码后感觉确实这么做是对的,但又说不出个所以然来。不过还是学到了点东西的:
拓扑排序时如果某一步将一个点去掉以后剩余点没有入度为零的,则说明原图中有环。
如果某一步发现入度为零的点不唯一,则说明拓扑排序结果不唯一。
思路:据说是拓扑排序典型题,大家自行看代码吧。。反正我几乎也是照搬别人的。。
代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int,int>P;
const int MAXN=100010;
int n,m;
int mp[30][30],temp[30],ind[30];//入度
string ans="";
int toposort()
{
ans.clear();
memcpy(temp,ind,sizeof(ind));
int flag=2;
for(int i=1;i<=n;i++)
{
int k=0,id;
for(int j=1;j<=n;j++)
if(temp[j]==0)
{
k++;
id=j;
}
if(k==0)return 1;
if(k>1)flag=0;
temp[id]=-1;
ans.push_back(id+64);
for(int j=1;j<=n;j++)
if(mp[id][j])
temp[j]--;
}
return flag;
}
int main()
{
char s[5];
while(scanf("%d%d",&n,&m),n+m)
{
int flag=0,temp;
memset(mp,0,sizeof(mp));
memset(ind,0,sizeof(ind));
for(int i=1;i<=m;i++)
{
scanf("%s",s);
if(!flag)
{
mp[s[0]-64][s[2]-64]=1;
ind[s[2]-64]++;
flag=toposort();
if(flag)
temp=i;
}
}
if(flag==1)
printf("Inconsistency found after %d relations.\n",temp);
else if(flag==2)
{
printf("Sorted sequence determined after %d relations: ",temp);
cout<<ans<<".\n";
}
else
printf("Sorted sequence cannot be determined.\n");
}
return 0;
}