poj1094 Sorting It All Out 拓扑排序 有向图判环 vector 模拟

来源:互联网 发布:php arrayaccess 编辑:程序博客网 时间:2024/06/05 04:37

                                       POJ 1094

题目大意:

输入n,m。n代表26个字母的前n个,m代表有m条输入。然后输入m条类似“A<B”形式的字符串,它代表第一个字符(A)小于第二个字符(B)。

然后根据这些字符关系,判断是否能找到一个唯一的序列使得满足这些字符的大小关系。(拓扑排序~)

如果可以的话,那么输出这个唯一的序列,不能的话,有两种情况,一是有环(A<B,B<C,C<A),二是不唯一。

这道题还明确的告诉你,从输入的第一个关系开始,如果在中途出现有环,或者可以输出正确序列,那么你可以直接输出答案。然后后续的输入就不用管了。。。

大体思路:

边输入边存图边判断,在判断期间,如果发现有环,那么就直接输出。如果能找到唯一满足n个字符的关系序列,那也直接输出。如果以上两种情况有一个发生,那么后续输入就不用管了。注意,当判断时,发现当前不能确定唯一的序列(这也有两种情况,一是出现的字符不足n个,二是入度数为零的不止一个),那我们也要判断是否有环(一直wrong的原因。。。),因为只要出现有环,就不可能进行拓扑排序

代码:

#include<stdio.h>#include<string.h>#include<iostream>using namespace std;#include<vector>#include<queue>vector<int>V[27];//用vector进行存图queue<int>Q;int anss[27];//用来打印正确序列int in[27];//存每个节点的入度数int inn[27];int ToPoSort(int n){    while(!Q.empty())Q.pop();    int num=0;    for(int i=1; i<=n; i++)    {        inn[i]=in[i];        if(in[i]==0)        {            num++;            Q.push(i);        }    }    if(num==0)return 0;//n个节点的入度数都为零,那么肯定是个环。    if(num>1)//有可能有的字符没出现,有可能是(B<C,A<C)这种情况,虽然这样num>1时,暂时不能找到正确序列,但我们依然要判环    {        //判环        int cou=0;        while(!Q.empty())        {            int top=Q.front();            cou++;            Q.pop();            int len=0;            while(len<V[top].size())            {                int temp=V[top][len];                inn[temp]--;                if(!inn[temp])Q.push(temp);                len++;            }        }        if(cou<n)            return 0;        return -1;    }    //num==1,我们要找正确序列了,但有环或者不唯一的话,也不行。    for(int i=1; i<=n; i++)    {        inn[i]=in[i];    }    int unq=0;    int cou=0;    while(!Q.empty())    {        if(Q.size()>1)unq=1;//不唯一        int top=Q.front();        anss[cou++]=top;        Q.pop();        int len=0;        while(len<V[top].size())        {            int temp=V[top][len];            inn[temp]--;            if(!inn[temp])Q.push(temp);            len++;        }    }    //cout<<"==="<<cou<<endl;    if(cou<n)return 0;//有环    if(unq)return -1;    return 1;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        for(int i=0; i<=27; i++)        {            V[i].clear();        }        memset(in,0,sizeof(in));        if(!n&&!m)break;        char a,c,b;        int flag=0;//当flag为1时,代表已经出现输出了,后续就不用管了        for(int i=1; i<=m; i++)        {            cin>>a>>c>>b;            if(flag)continue;            in[b-'A'+1]++;            V[a-'A'+1].push_back(b-'A'+1);            int ans=ToPoSort(n);//边输入边存图边判断            if(ans==0)            {                printf("Inconsistency found after %d relations.\n",i);                flag=1;            }            else if(ans==1)            {                printf("Sorted sequence determined after %d relations: ",i);                for(int i=0; i<n; i++)                {                    printf("%c",anss[i]-1+'A');                }                printf(".\n");                flag=1;            }        }        if(!flag)        {            printf("Sorted sequence cannot be determined.\n");        }    }}

这道题的思路不难,不过代码实现时,要考虑很多,多思考。。。