1. 程式人生 > >POJ1094 Sorting It All Out

POJ1094 Sorting It All Out

front break con min ack lag cstring 出錯 循環

POJ1094 Sorting It All Out

題目鏈接:http://poj.org/problem?id=1094

題意:這個題意確定是有點難懂,給你n個點,和m條邊。問你在添加多少條邊以後n個點的拓撲順序是確定的,或者在添加多少條邊以後出現了環,如果添加完所有的邊,還存在有些點之間不可排序,就說明這些關系不足以排序的。

思路:一旦n個點的已經存在拓撲關系,或者出現環,就可以結束循環了,當添加完所有的點依然無法得到n個點之間的拓撲關系,或者環,就說明無法排序的。等於說加一條邊,拓撲排序一次,這裏註意,如果既出現環又出現點和點之間關系不確定的情況,我們還是認出現環,不出現環,出現了點和點之間關系不確定,我們才認關系不確定,剩下的就是已經排好序的。要確定他們的先後關系,不然在return的時候,可能會出錯。基礎的拓撲排序,只是多了一下判斷和滿足條件。理清他們的滿足條件之間的關系,問題就是可以迎刃而解。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
const int N=26;
using namespace std;
struct d{
    char a,b,c;
}oj[100000];
int in[N],tin[N],ans[N],len;
vector<int>p[N];
int n,m,k;
int topo(){
    queue<int>q;
    k=0;
    memset(tin,
0,sizeof(tin)); for(int i=0;i<n;i++) if(!in[i]) {q.push(i);} int flag=0; len=0; while(!q.empty()){ if(q.size()>1) flag=1; int t=q.front();q.pop(); ans[k++]=t; for(int i=0;i<p[t].size();i++){ int s=p[t][i]; if(++tin[s]==in[s]){ q.push(s); } } }
if(k<n) return -1; else if(flag) return 0; return 1; } int main(){ while(cin>>n>>m&&(n+m)){ for(int i=0;i<N;i++) p[i].clear(); memset(in,0,sizeof(in)); for(int i=0;i<m;i++){ cin>>oj[i].a>>oj[i].b>>oj[i].c; } int hl=-1,ul=-1; for(int i=0;i<m;i++){ int x=oj[i].a-A, y=oj[i].c-A; if(oj[i].b==>){ p[x].push_back(y); in[y]++; } else if(oj[i].b==<){ p[y].push_back(x); in[x]++; } int t=topo(); if(t==1){ hl=i+1; break; } else if(t==-1){ ul=i+1; break; } } if(hl!=-1){ cout<<"Sorted sequence determined after "<<hl<<" relations: "; for(int i=n-1;i>=0;i--) putchar(A+ans[i]);cout<<.; } else if(ul!=-1){ cout<<"Inconsistency found after "<<ul<<" relations."; } else cout<<"Sorted sequence cannot be determined."; cout<<endl; } return 0; }

判斷是否出現環:拓撲排序中遍歷的點的點數小於n,說明出現了環

判斷是否出現無法比較的兩個點:拓撲排序中的隊列如果同時存在兩個元素,說明這兩個元素是無法比較的

POJ1094 Sorting It All Out