您的位置:首页 > 其它

拓扑排序_Poj_1094

2011-07-23 12:08 169 查看
/*
文章大意是将n个字母排序(n<=26)。
最终必须排成链表式的输出
一旦确定或者出现环,记录当前步数,后续输入无视
*/
/*
加个拓扑排序判断图的总结:
1、如果输入的有向图中的点,不存在入度为0的点,则存在回路,反过来则不成立
2、如果入队的点的个数小于输入的点的个数,则肯定存在回路
3、如果存在的入度为零的点大于一个,则肯定不存在一个可以确定的序列
*/

//解法1:拓扑排序解法

#include<iostream>
#include<vector>
#include<string>
#include<queue>
#include<list>

using namespace std;

#define UnSure 0 //不确定
#define Cycle 1//有环
#define Sorted 2//已排好序

int n;//输入个数

vector<list<int> > g; // 图
vector<int> top; //拓扑序列
vector<int> ins; //入度

//辅助变量
int i,j;

int topsort()
{
bool unsure = false;
queue<int> que;
vector<int> ins2(ins.begin(),ins.end());//建立入度副本
int u;
for(i=0;i<n;i++)
{
if(ins[i]==0) que.push(i);
}
list<int>::iterator it;
top.clear();
while(!que.empty())
{
if(que.size()!=1) unsure=true;
u=que.front(),que.pop();
top.push_back(u);
for(it=g[u].begin();it!=g[u].end();it++)
{
if(--ins2[*it]==0)
{
que.push(*it);
}
}
}
if(top.size()!=n) return Cycle;
else if(unsure) return UnSure;
return Sorted;
}

int main()
{
int m; //关系数
while(cin>>n>>m,m!=0||n!=0)
{
int steps = 0; //步数
int status = UnSure;//当前状态
string rel;
g.assign(n,list<int>());//建立相连表
ins.assign(n,0);//建立入读表
int u,v;
for(steps=0;steps<m && status==UnSure;steps++)
{
cin>>rel;
u=int(rel[0]-'A'),v=int(rel[2]-'A');
if(find(g[u].begin(),g[u].end(),v)==g[u].end())//u,v边未存在则插入链表
g[u].push_back(v),ins[v]++;
status = topsort();
}
for(i=steps;i<m;i++) cin>>rel;//处理无用的字符串
if(status == Sorted)
{
printf("Sorted sequence determined after %d relations: ",steps);
for(i=0;i<top.size();i++)
printf("%c",top[i]+'A');
printf(".\n");
}
else if(status == Cycle)
{
printf("Inconsistency found after %d relations.\n",steps);
}
else
{
printf("Sorted sequence cannot be determined.\n");
}
}
return 0;
}

//解法2:用二维数组实现记录彼此之间的关系

#include<iostream>
using namespace std;

int m,n;
int a[26][27];
bool b[26];
int i,j,l,x,y;
char k[4];
int suc,fail;
bool IsOk,_ok;

bool init()
{
//定义bool变量用来判断是否成功
IsOk = true,_ok = false;
//初始化
suc=fail=-1;
memset(a,0,sizeof(a));
//输入并初始化
for(i=0;i<n;i++)
{
scanf("%s",k);
if(IsOk&&!_ok)
{
x=k[0]-'A';
y=k[2]-'A';
a[x][y]=1;
if(a[y][x]==1)
{
IsOk = false;
fail = i;
}
if(IsOk)
{
//小于X的都小于Y 记录下来
for(j=0;j<m;j++)
{
if(a[j][x])
{
a[j][y]=1;
if(a[y][j])
{
IsOk=false;
fail = i;
break;
}
}
}
//大于Y的都大于X,记录下来
for(j=0;j<m;j++)
{
if(a[y][j])
{
a[x][j]=1;
if(a[j][x])
{
IsOk=false;
fail = i;
break;
}
}
}
}
if(!IsOk) continue;
if(!_ok)
{
//**每次输入一次就判断是否已经判断完成**
//统计每行的数字
int sum;
for(j=0;j<m;j++)
{
sum=0;
for(l=0;l<m;l++)
{
sum+=a[j][l];
}
a[j][26]=sum;
}
//判断每行的数字是不是都唯一。
memset(b,0,sizeof(b));//记录是否已经访问过
for(j=0;j<m;j++)
{
for(l=0;l<m;l++)
{
if(b[l]) continue;
else if(a[l][26]==j)
{
b[l]=true;
break;
}
}
if(l==m) break;//没找到要的数字
}
if(j==m)
{
_ok=true;
suc=i;
}//成功
}
}
}
return IsOk;
}


int main()
{
while(scanf("%d%d",&m,&n)&&(m!=0||n!=0))
{
bool u = init();
if(u&&_ok)
{
//成功,则输出
printf("Sorted sequence determined after %d relations: ",suc+1);
for(j=m-1;j>-1;j--)
{
for(l=0;l<m;l++)
{
if(a[l][26]==j)
{
printf("%c",'A'+l);
break;
}
}
}
printf(".\n");
}
else if(u)
{
printf("Sorted sequence cannot be determined.\n");
}
else
{
printf("Inconsistency found after %d relations.\n",fail+1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: