Description
AC哥打算去很多个地方旅游,他已经列好了一份清单,一共有N个城市要去。但是AC哥还有个强迫症,就是对于某些城市,他要去安排在其它特定的一个甚至多个城市旅行完之后才去,于是他有制定了一份顺序计划。比如A城市如果要求排在B和C后面,那么他就必须先去B和C旅行,然后才能去A。
然而,聪明如AC哥,他竟然没注意到,他的计划表可能出现死循环,即诸如城市A安排在城市B后面,城市B安排在城市C后面,C又安排在A后面,这样最终其实他三个都去不了。现在,你需要根据这份计划表,告诉AC哥他有多少个城市实际上是去不了的。
Input
第一行输入一个整数T,表示有T组数据。
每组数据先输入一个整数N,M,表示有N个城市,以及M个限制条件。
接着一行有N个字符串,代表城市名字,字符串只包含小写字母,字符串之间用空格隔开。
接下来M行,每行都是两个字符串X和Y,表示去X之前一定要先去Y,这里X和Y保证不相同。
数据范围
1 <= T <= 20
1 <= N <= 10000
0 <= M <= 20000
城市名字都是长度不超过20,且仅由小写字母构成。
Output
对于每组数据,输出一行“Case #k: r”,其中k为数据编号,从1开始。r为结果,即AC哥最终没法去的城市的数量。
Sample Input
3
3 3
a b c
a b
b c
c a
3 2
guangzhou shenzhen dongguan
guangzhou shenzhen
guangzhou dongguan
4 2
guangzhou shenzhen dongguan huizhou
shenzhen huizhou
huizhou shenzhen
Sample Output
Case #1: 3
Case #2: 0
Case #3: 2
真心感谢大师兄。
大师兄天下第一!
拓扑排序的O(M+N)写法。
1、记录每个点的入度 2、把所有度数为0的点放到队列
3、循环处理队列,把队首元素取出来,然后把它指向的所有点的度数减一,如果有点的度数减到0了,就加到队列,直到队列空为止
复杂度O(N+M),N是点数,M是边数
public class Main {
@SuppressWarnings("unchecked")
static ArrayList<Integer> G[] = new ArrayList[10005];
static int[] deg = new int[10005];
static HashMap<String, Integer> name = new HashMap<String, Integer>();
public static void main(String[] args) {
// Scanner reader = new Scanner(System.in);
InputReader reader = new InputReader();
PrintWriter out = new PrintWriter(System.out);
int t = reader.nextInt();
int cases = 1;
while (t-- > 0) {
int n = reader.nextInt();
int m = reader.nextInt();
out.print("Case #" + (cases++) + ": ");
for (int i = 1; i <= n; i++) {
name.put(reader.next(), i);
}
for (int i = 1; i <= n; i++) {
G[i] = new ArrayList<Integer>();
}
while (m-- > 0) {
int to = name.get(reader.next());
int from = name.get(reader.next());
G[from].add(to);
deg[to]++;
}
int count = 0;
Queue<Integer> wait = new LinkedList<Integer>();
for (int i = 1; i <= n; i++) {
if (deg[i] > 0) {
continue;
}
wait.add(i);
count++;
}
while (!wait.isEmpty()) {
int get = wait.poll();
for (int i = 0, len = G[get].size(); i < len; i++) {
if (--deg[G[get].get(i)] == 0) {
wait.add(G[get].get(i));
count++;
}
}
}
out.println(n - count);
name.clear();
Arrays.fill(deg, 1, n + 1, 0);
}
out.close();
}
}