http://poj.org/problem?id=1094
方法:
每加入一条边就进行一次拓扑排序,从而找到符合条件的最少边数
拓扑排序的基本思想就是依次找到图中入度为0的节点,将该节点和其对应的边删除,这样就使得它的邻接节点的入度-1。反复循环这样做直到所有节点都从图中删除(都被编上拓扑编号),或者因为有环所以还剩下某些节点未被删除
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.
1:
2: #include <stdio.h>
3: #include <iostream>
4: #include <queue>
5: #include <set>
6: #include <vector>
7: #include <string>
8: #include <fstream>
9:
10: using namespace std ;
11:
12: const int N=26 ;
13: typedef vector< vector<char> > Graph ;
14:
15: void run1094()
16: {
17: //ifstream in("in.txt") ;
18:
19: Graph G ;
20: set<char> vertexSet ;
21:
22: int n,m ;
23: int relnum ;
24: int i,cnt ;
25: bool sucFlag,cyFlag,notdeterFlag ;
26: char s,t,vertex ;
27:
28: set<char>::iterator sIter ;
29: vector<char>::iterator vIter ;
30:
31: //while( scanf( "%d%d", &n,&m ) && n!= 0 )
32: while(cin>>n>>m && n!=0)
33: {
34: vertexSet.clear() ; //一定注意使用容器前要clear
35: G.clear() ;
36: G.resize(N) ;
37: string *relation = new string[m] ;
38: int indegree[N] = {0} ;
39: int tmpIndegree[N]= {0} ;
40: char topnum[N] = {0} ;
41:
42: sucFlag = false ;
43: cyFlag = false ;
44:
45: i = 0 ;
46: while( i < m )
47: cin>>relation[i++] ;
48:
49: //对关系数从1~m枚举,每次往图中增加一条边而得到一个新图,对该图拓扑排序以找到符合条件的最小的关系数(边数)
50: for( relnum=1 ; relnum<=m ; ++relnum )
51: {
52: notdeterFlag = false ; //***每次循环需要将其初始化
53:
54: queue<char> Q ;
55: for( i=0 ; i<n ; ++i )
56: topnum[i] = 0 ;
57:
58: //得到此时的图的邻接表,vertexSet中存放的是当前图中的节点
59: s = relation[relnum-1][0] ;
60: t = relation[relnum-1][2] ;
61: vertexSet.insert(s) ;
62: vertexSet.insert(t) ;
63: G[s-'A'].push_back(t) ; //更新邻接表
64: ++indegree[t-'A'] ; //更新indegree
65:
66: for( i=0 ; i<N ; ++i )
67: tmpIndegree[i] = indegree[i] ; //复制此时的indegree,因为需要改变此数组
68:
69: //找到初始时入度为0的vertex
70: for( sIter=vertexSet.begin() ; sIter!=vertexSet.end() ; ++sIter )
71: {
72: if( tmpIndegree[*sIter-'A']==0 )
73: Q.push(*sIter) ;
74: }
75: //任何时刻当入度为0的vertex多于1个时,则拓扑排序的结果不唯一
76: //此时将notdeterFlag置为true表示该暂时图的拓扑结果不唯一
77: if( Q.size() > 1 )
78: notdeterFlag = true ;
79:
80: //循环进行拓扑排序
81: cnt = 0 ;
82: while( !Q.empty() )
83: {
84: vertex = Q.front() ;
85: Q.pop() ;
86: topnum[cnt++] = vertex ; //分配拓扑排序编号
87:
88: //将需要从图中删除的节点的边也删除掉,这意味着它的所有邻接点的入度-1
89: for( vIter=G[vertex-'A'].begin() ; vIter!=G[vertex-'A'].end() ; ++vIter )
90: {
91: //所有邻接点的入度-1,并将入度减为0的节点入队等待分配拓扑排序编号
92: if( --tmpIndegree[*vIter-'A'] == 0 )
93: Q.push(*vIter) ;
94: }
95: //任何时刻当入度为0的vertex多于1个时,则拓扑排序的结果不唯一
96: if( Q.size() > 1 )
97: notdeterFlag = true ;
98: }
99:
100: //若该暂时图所有节点还没有全部被排序,就已经找不出入度为0的节点了,则证明该图有环
101: //跳出判断循环并输出结果“有环”
102: if( cnt!=vertexSet.size() )
103: {
104: cyFlag = true ;
105: break ;
106: }
107:
108: //若该图已被排序,并且排序结果唯一(由notdeterFlag为false决定)
109: //同时被排序的节点数等于完整图中的所有节点的个数
110: //跳出判断循环并输出结果“可以唯一地排序”
111: if( !notdeterFlag && cnt==n )
112: {
113: sucFlag = true ;
114: break ;
115: }
116: }
117: delete []relation ;
118:
119: if( sucFlag )
120: {
121: printf( "Sorted sequence determined after %d relations: " , relnum );
122: for( i=0 ; i<n ; ++i )
123: printf( "%c" , topnum[i] ) ; //输出char用%c
124: printf( ".\n" ) ;
125: }
126: else if( cyFlag )
127: printf( "Inconsistency found after %d relations.\n" , relnum ) ;
128: else if( notdeterFlag )
129: printf( "Sorted sequence cannot be determined.\n" ) ;
130: }
131: }