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

//拓扑排序。每添一条边就进行一次拓扑排序 #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; }  

你可能感兴趣的:(POJ 1094 Sorting It All Out(拓扑排序))