一、问题描述
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 }
四、感想
自己通过自己独立分析问题,自己独立编程实现,最后这个题目AC,这个节奏还是很好的~
最后,YZY,我想你!~
浙公网安备 33010602011771号