poj 1094 Sorting It All Out(拓扑排序·环·矩阵)

题目:http://poj.org/problem?id=1094

Sorting It All Out
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 30357   Accepted: 10518

Description

An ascending sorted sequence of distinct values is one in which some form of a less-than operator is used to order the elements from smallest to largest. For example, the sorted sequence A, B, C, D implies that A < B, B < C and C < D. in this problem, we will give you a set of relations of the form A < B and ask you to determine whether a sorted order has been specified or not.

Input

Input consists of multiple problem instances. Each instance starts with a line containing two positive integers n and m. the first value indicated the number of objects to sort, where 2 <= n <= 26. The objects to be sorted will be the first n characters of the uppercase alphabet. The second value m indicates the number of relations of the form A < B which will be given in this problem instance. Next will be m lines, each containing one such relation consisting of three characters: an uppercase letter, the character "<" and a second uppercase letter. No letter will be outside the range of the first n letters of the alphabet. Values of n = m = 0 indicate end of input.

Output

For each problem instance, output consists of one line. This line should be one of the following three: 

Sorted sequence determined after xxx relations: yyy...y. 
Sorted sequence cannot be determined. 
Inconsistency found after xxx relations. 

where xxx is the number of relations processed at the time either a sorted sequence is determined or an inconsistency is found, whichever comes first, and yyy...y is the sorted, ascending sequence. 

Sample Input

4 6
A<B
A<C
B<C
C<D
B<D
A<B
3 2
A<B
B<A
26 1
A<Z
0 0

Sample Output

Sorted sequence determined after 4 relations: ABCD.
Inconsistency found after 2 relations.
Sorted sequence cannot be determined.
分析:很经典的拓扑排序。矛盾关系的产生(Inconsistency found after xxx relations. )是因为在有向图中产生了环;大小关系的确定(Sorted sequence determined after xxx relations: yyy...y. )是整个有向图的拓扑排序已经完成;无法确定整个序列的单调关系(Sorted sequence cannot be determined. )则是m条有向边建立完了后仍然没有前两者的判断结果。完成它确实不容易,TLE了4次,WA了4次,前者是因为没有搞懂"after xxx relations."这句话的内涵,需要每次建立新边后立即判断一下有没有环,完没完成拓扑排序,如果判断了则输出结果,后面只需要输入剩下的关系就可以了,如果m条有向边建立完成了都没有前两个的判断结果,那么就是无法确定结果。WA的原因我是真没看出来,后来换了一种写法(模仿||-_-)才过的。
为逝去的代码默哀三分钟:WA
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int head[30],indeg[30],n,m,sum;
struct node{
    int to,next;
}edge[30];
bool vis[30];
void init(){
    sum=0;
    memset(vis,0,sizeof(vis));
    memset(indeg,0,sizeof(indeg));
    memset(head,-1,sizeof(head));
    memset(edge,0,sizeof(edge));
}
void addedge(int u,int v){
    vis[u]=vis[v]=1;
    edge[sum].to=v;
    edge[sum].next=head[u];
    head[u]=sum++;
    indeg[v]++;
}
int report(){
    int res=0;
    for(int i=0;i<n;i++){
        if(vis[i]) res++;
    }
    return res;
}
int que[30],top;
int topo(){  // 1: not determined  2: inconsistent 有环矛盾  3: OK
    top=0;
    int ing[30],all=report();
    for(int i=0;i<n;i++)  ing[i]=indeg[i];
    for(int i=0;i<n;i++){
        if(ing[i]==0&&vis[i]){  que[top++]=i;  ing[i]--; }  //printf("%c\n",i+'A');
    }
    if(top==0) return 2; //大环
    for(int i=0;i<top;i++){
        for(int j=head[que[i]];j>-1;j=edge[j].next){
            ing[edge[j].to]--;
            if(ing[edge[j].to]==0&&vis[j]){
                 que[top++]=edge[j].to;
                 ing[edge[j].to]--;
            }
        }
    }
    if(top==n) return 3;
    if(top<all) return 2; //小环
    return 0;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    char str[5];
    int flag;
    while(cin>>n>>m&&(n+m)){
        init();
        flag=0;
        for(int i=0;i<m;i++){
            scanf("%s",str);
            if(flag) continue;
            addedge(str[0]-'A',str[2]-'A');
            flag=topo();
            if(flag){
                if(flag==3) {
                    printf("Sorted sequence determined after %d relations: ",i+1);
                    for(int j=0;j<n;j++){  printf("%c",que[j]+'A'); }
                    puts(".");
                }
                else if(flag==2)printf("Inconsistency found after %d relations.\n",i+1);
            }
        }
        if(!flag) puts("Sorted sequence cannot be determined.");
    }
    return 0;
}

接下来是正确的:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n,m,sum;
int map[30][30],indeg[30],que[30],top;
int topo(){ // 1:OK  2: 有环,矛盾 3:not sure
    int ing[30],loc,flag=1;
    top=0;
    for(int i=0;i<n;i++) ing[i]=indeg[i];
    for(int i=0;i<n;i++){
        int sum=0;
        for(int j=0;j<n;j++){
            if(ing[j]==0){  sum++;  loc=j; }  //把"ing[loc]--;"放在这里面会
        }  //提前让两个剩余的点由0变-1,进而得到sum==0的后果
        if(sum==0) return  2;
        if(sum>1)  flag=3;
        que[top++]=loc;
        ing[loc]--;
        for(int j=0;j<n;j++)
           if(map[loc][j]) ing[j]--;
    }
    return flag;
}
int main()
{
    //freopen("cin.txt","r",stdin);
    char str[5];
    while(cin>>n>>m&&(n+m)){
        memset(map,0,sizeof(map));
        memset(indeg,0,sizeof(indeg));
        bool tag=0;
        for(int i=0;i<m;i++){
            scanf("%s",str);
            if(tag) continue;
            int x=str[0]-'A',y=str[2]-'A';
            map[x][y]=1;
            indeg[y]++;
            int p=topo();
            if(p==2){
                 printf("Inconsistency found after %d relations.\n",i+1);
                 tag=1;
            }
            else if(p==1){
                 printf("Sorted sequence determined after %d relations: ",i+1);
                 for(int j=0;j<n;j++) printf("%c",que[j]+'A');
                 puts(".");
                 tag=1;
            }
        }
        if(!tag) puts("Sorted sequence cannot be determined.");
    }
    return 0;
}


你可能感兴趣的:(poj,拓扑排序)