一、问题描述

              POJ_1094:http://poj.org/problem?id=1094

              输入:

              给定字母个数n(从A开始计数),给定偏序关系个数

              下面是一系列偏序关系

              输出:

              分为3种

              1、在第i个关系之后,找到唯一的拓扑排序序列

              2、拓扑排序不唯一

              3、在第i个关系之后,发现圈

 

         二、需要解决的问题

              问题有3个:

              第一个问题:怎么确定加入第i个关系出现回路?

              解决办法之一:首先,判断一个图是不是有回路的方法是,把DFS稍加修改,在从节点u的邻接节点中取出一个节点,如果该节点是灰色的,则出现回路。这道题要求每次加入新的关系时,都要判断是不是出现回路。例如,新加入的关系是A<B,那么可以从A节点开始DFS,判断是否出现回路。

              第二个问题:怎么找到拓扑排序?

              解决办法之一:使用DFS的过程中,先完成的节点插入到链表的头部。

              第三个问题:怎么判断是不是唯一的拓扑排序?

              解决办法之一:找到一个拓扑排序之后,例如ACBD,我们检查A/C、C/B、B/D两两之间是不是都有边,如果都有边,则可以判定是唯一的拓扑排序。

 

         三、程序实现

              这道题,其实,如果去掉要求输出到哪个关系找到唯一拓扑排序或者出现回路这个要求,其实算法很简单,而且代码也清晰简单。但是,加上这些关系,加上之前没有好好构思,导致,这个程序是在一边写一边改,导致程序看起来很乱~~

              而且,加上读题不仔细,之前以为“如果在第i个关系之后,找到唯一的拓扑排序,但是后面的关系可能会出现回路,这时应输出发现回路”,其实题目要求是找到唯一的拓扑排序和出现回路哪个先出现,最后就输出哪个~这个导致WA了几次~

  1 #include<iostream>
  2 #include<string>
  3 #include<list>
  4 using namespace std;
  5 
  6 #define WHITE 1
  7 #define GRAY 2
  8 #define BLACK 3
  9 
 10 struct node{
 11     int ru; //入度是否为零
 12     list<int> l;
 13 };
 14 
 15 node *s;//矩阵实现的图
 16 int *color;//标志数组
 17 int *xu_final;//最后的拓扑排序
 18 list<int> xu;//最后的拓扑排序
 19 int a = 0;
 20 int time = 0;//第几个关系
 21 int ttime = 0;
 22 int res = 1;//0表示有环 1表示状态没改变 2表示唯一
 23 
 24 //DFS
 25 void DFS(int i ,int flag)
 26 {
 27     color[i] = GRAY;
 28     
 29     list<int>::iterator it;
 30     it = s[i].l.begin();
 31     for(;it != s[i].l.end();++it)
 32     {
 33         if(color[(*it)] == GRAY)
 34         {
 35             //有圈
 36             res = 0;
 37             if(ttime == 0)
 38             ttime = time;
 39         }
 40         if(color[(*it)] == WHITE)
 41         {
 42             DFS(*it , flag);
 43         }
 44     }
 45     color[i] = BLACK;
 46     if(flag)
 47        xu.push_front(i);
 48 }
 49 //寻找入度为零的点
 50 int SearchZero()
 51 {
 52     //寻找入度为零的点
 53         int f = -1;
 54         for(int i = 0;i < a;i++)
 55         {
 56             if(s[i].ru && f==-1)
 57                 f = i; //第一个入度为零的点
 58         }
 59         if(f != -1) return f;
 60         else return -1;
 61 }
 62 
 63 //初始化color数组
 64 void Reset()
 65 {
 66     //初始化 color
 67     color = new int[a];
 68     for(int i = 0 ;i < a;i++)
 69         color[i] = WHITE;  //初始为white
 70 }
 71 
 72 //判断是否找到
 73 int findAll()
 74 {
 75     for(int i = 0;i < a;i++)
 76         if(color[i] == WHITE)
 77              return 0;
 78     return 1;
 79 }
 80 
 81 //判断是不是唯一
 82 int isOne()
 83 {
 84     int kk = 0;
 85     if(xu_final[0] != -1)
 86                 for(int h = 0;h < a-1;h++)
 87                 {
 88                    list<int>::iterator it;
 89                    it = s[xu_final[h]].l.begin();
 90                    for(;it != s[xu_final[h]].l.end();it++)
 91                        if((*it) == xu_final[h+1])
 92                         {
 93                            kk++;
 94                            break;
 95                         }
 96                 }
 97      return kk;
 98 }
 99 int main()
100 {
101     int b = 0;
102     while(cin >> a >> b)
103     {
104         if(a == b && a == 0)
105              break;
106 
107         //初始化 s
108         s = new node[a];
109         for(int i = 0;i < a;i++)
110             s[i].ru = 1;
111 
112         time = 1;
113         ttime = 0;
114         res = 1;
115         int find_time = 0;
116 
117         xu_final = new int[a];
118 
119         xu_final[0] = -1;
120 
121         while(b)
122         {
123             string str;
124             cin >> str;
125             
126             int i1 = str[0] - 'A';
127             int i2 = str[2] - 'A';
128             
129             s[i2].ru = 0;
130             (s[i1].l).push_back(i2);
131             
132             if(res == 1)
133             {
134             Reset();
135             DFS(i1 , 0);
136                 Reset();
137                 if(SearchZero() != -1)
138                 DFS(SearchZero() , 1);  //从第一个入度为零的点进行DFS  第二个例子中,2个关系之后,C的入度为零.....
139                 if(!find_time && findAll())
140                 {
141                         list<int>::iterator itt;
142                         itt = xu.begin();
143                         int ll = 0;
144                         for(;itt != xu.end();itt++)
145                         {
146                             xu_final[ll] = *itt;
147                             ll++;
148                         }
149                         if(isOne() == a-1){ res = 2;find_time = time;}
150                 }
151             }
152             xu.clear();
153             time++;
154             b--;
155         }
156         if(res == 2)
157         {
158             //唯一的拓扑排序
159             cout<<"Sorted sequence determined after "<<find_time<<" relations: ";
160             for(int hh = 0;hh < a;hh++)
161                 cout<<(char)(xu_final[hh]+65);
162             cout <<"."<< endl;
163         }
164         else if(!res)
165         {
166             cout << "Inconsistency found after "<<ttime<<" relations."<<endl;
167         }
168         else
169         {
170             //不唯一
171             cout << "Sorted sequence cannot be determined."<<endl;
172         }
173         for(int i = 0;i < a;i++)
174             s[i].l.clear();
175         }
176     return 0;
177 }
View Code

 

          四、感想

                自己通过自己独立分析问题,自己独立编程实现,最后这个题目AC,这个节奏还是很好的~

                最后,YZY,我想你!~ 

              

posted on 2014-03-18 11:57  Oloo  阅读(187)  评论(0)    收藏  举报