您的位置:首页 > 其它

POJ 1094 Sorting It All Out(拓扑排序)

2010-06-09 08:44 387 查看
//拓扑排序。每添一条边就进行一次拓扑排序
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int inDeg[26];
int n,m,time,u,v;
int appear;//已出现的结点数
char str[3],topo[26];
bool vis[26];
vector<int> e[26];
queue<int> q;
//思路:
//此题有个判断的优先级隐含在里面:最高级是确定排序,次之是判断图中是否存在环,最后才是无法确定排序,需要添加新边
//1.在可以确定唯一排序的情况下从队列里面弹出一个结点,说明此结点排序成功,sorted+1,如果sorted = n则说明已确定排序情况
//2.如果初始状态全部结点入度不为0,则此图已经是环
//2.当队列为空时,从队列里面出来的结点数目小于以出现过的总结点数目,则确定图中有环
//3.如果入度为0的结点超过1个且此图不存在环,则此图不能唯一确定排序,需要添加新边
//必须先判断是否存在环,再确定此图无法确定排序!!WA了我3次
int toposort()//返回0表示存在环,返回1表示需要新边才能得出唯一排序,返回2表示已经得出排序
{
int Deg[26];//开多一个数组来临时存放添加新边后的入度情况
int sorted = 0;
bool needNewEdge = 0;
int node = 0;
memcpy(Deg,inDeg,sizeof(inDeg)); //复制inDeg到Deg
for(int i = 0;i < n;++i)
if(Deg[i] == 0)
q.push(i);
if(q.empty())	return 0;//如果没有入度为0的结点,则说明图中存在了环
if(q.size() > 1)	needNewEdge = 1;//如果队列中入度为0的结点超过1个,则说明无法确定的排序情况,因为无法比较多个互不相连的点的大小,此时需要添加新边.用needNewEdge表示需要添加边
while(!q.empty())
{
u = q.front();
q.pop();
++node;//从队列里面出来的结点个数+1
int cnt = 0;
for(int i = 0;i < e[u].size();++i)
{
if(--Deg[e[u][i]] == 0)//与u相邻的每个点入度都减1
{
q.push(e[u][i]);
++cnt;
}
}
if(cnt > 1)	needNewEdge = 1;//添加了超过1个入度为0的结点,需要新边
if(!needNewEdge)	topo[sorted++] = u + 'A';//在不需要添加新边的状态下sortd才会增加,在无法确定唯一排序的情况下继续操作是为了确定图中是否存在环
}
if(sorted == n)	return 2;
if(node < appear)	return 0;//如果从队列里面出来的结点数<已出现过的结点数,返回0,存在环
if(sorted == appear|| needNewEdge)	return 1;//如果已成功确定排序的个数=出现过的结点数,并且sorted != n则说明需要需要添加新边
}
int main()
{
freopen("in.txt","r",stdin);
while(scanf("%d%d",&n,&m) && n != 0)
{
bool goon = 1,impossible = 1;
for(int i = 0;i < 26;++i)	e[i].clear();
memset(inDeg,-1,sizeof(inDeg));//记录入度的数组
memset(vis,0,sizeof(vis));
time = appear = 0;

while(m-- && goon)
{
++time;//记录已添加的边数
scanf("%s",str);
u = str[0] - 'A';
v = str[2] - 'A';;
if(!vis[u])
{
++appear;
vis[u] = 1;
}
if(!vis[v])
{
++appear;
vis[v] = 1;
}//标记添加新边的时候出现的新结点,并记录个数
e[u].push_back(v);//邻接表存放边
inDeg[u] = (inDeg[u] < 0 ? 0 : inDeg[u]);
inDeg[v] = (inDeg[v] < 0 ? 1 : ++inDeg[v]);//更新入度
int res = toposort();//拓扑排序
if(res == 0)
{
printf("Inconsistency found after %d relations./n",time);
while(m--){scanf("%s",str);}//读完剩余的边
goon = 0;
impossible = 0;
}
else if(res == 2)
{
printf("Sorted sequence determined after %d relations: %s./n",time,topo);
while(m--){scanf("%s",str);}//读完剩余的边
goon = 0;
impossible = 0;
}
else continue;
}
if(impossible)//读完所有的边仍然无法确定排序
printf("Sorted sequence cannot be determined./n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: