zoj1060 poj1094 Sorting It All Out
题意:给出两个整数 n m n代表前n个大写字母参与 m代表m个表达式
根据给出的m个式子 将最终符合要求的顺序输出
有三种结果 1.能够根据给出的表达式求出排序的序列 且输出到第几个表达式就能得到结果
2.有环的情况 序列有好几种情况满足要求 且输出到第几个表达式能判断此情况
3.参与的字母数小于n 序列的情况不能得到决定
代码如下(如何正确处理已经取出的字母 以及如何保存结果很重要):
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string.h>
#include <string>
#define eps 1e-8
#define op operator
#define MOD 10009
#define MAXN 10000
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define FOV(i,a,b) for(int i=a;i>=b;i--)
#define REP(i,a,b) for(int i=a;i<b;i++)
#define REV(i,a,b) for(int i=a-1;i>=b;i--)
#define MEM(a,x) memset(a,x,sizeof a)
#define ll __int64
using namespace std;
int map[30][30],rd[30],seq[30];
int topsort(int n)
{
int flag=1,cnt=0,temp[30];
for(int i=1;i<=n;i++)
{
temp[i]=rd[i];
// cout<<"i:"<<i<<" "<<temp[i]<<endl;
}
int pos;
for(int i=1;i<=n;i++)
{
int m=0;
for(int j=1;j<=n;j++)
if(temp[j]==0)
{
m++; pos=j;
}
// cout<<"m:"<<m<<endl;
if(m==0) return 0;//有环
if(m>1) flag=-1;//有至少两个点入度为0 不能判断
seq[cnt++]=pos;
temp[pos]=-1;//将这个点的入度设为负 以免重复判断
for(int j=1;j<=n;j++)
if(map[pos][j]==1)
temp[j]--; //将以pos开始的边删去
}
return flag;
}
int main()
{
//freopen("ceshi.txt","r",stdin);
int n,m;
while(scanf("%d%d\n",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
int flag=0;
MEM(map,0);
MEM(rd,0);
for(int i=1;i<=m;i++)
{
//cout<<"i "<<i<<endl;
char ch[5];
scanf("%s",ch);
if(flag) continue;
int x,y;
x=ch[0]-'A'+1;
y=ch[2]-'A'+1;//将大写字母换成数字 从1开始
map[x][y]=1;
rd[y]++;
// cout<<"rd y:"<<rd[y]<<" "<<y<<endl;
int s=topsort(n);
// cout<<s<<endl;
if(s==0)
{
printf("Inconsistency found after %d relations.\n",i);
flag=1;
}
if(s==1)
{
printf("Sorted sequence determined after %d relations: ",i);
for(int i=0;i<n;i++)
{
printf("%c",seq[i]+'A'-1);
}
printf(".");
puts("");
flag=1;
}
}
if(!flag) printf("Sorted sequence cannot be determined.\n");
}
return 0;
}