思路:
拓扑排序。贪心。
实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 vector<int> G[100005]; 4 int n1, n2; 5 inline void help(queue<int>& a, queue<int>& b, int x) 6 { 7 if (x > n1) b.push(x); 8 else a.push(x); 9 } 10 bool same(int x, int y) 11 { 12 if (x >= 1 && x <= n1 && y >= 1 && y <= n1) return true; 13 if (x > n1 && y > n1) return true; 14 return false; 15 } 16 int cal(queue<int> a, queue<int> b, vector<int>in, bool set) 17 { 18 int cnt = 0, last = -1, rnd = 0; 19 while (!a.empty() || !b.empty()) 20 { 21 if ((!set && rnd) || set) 22 { 23 while (!a.empty() && !in[a.front()]) 24 { 25 int tmp = a.front(); a.pop(); 26 if (!same(tmp, last)) cnt++; 27 last = tmp; 28 for (int i = 0; i < (int)G[tmp].size(); i++) 29 { 30 int son = G[tmp][i]; 31 if (--in[son] == 0) help(a, b, son); 32 } 33 } 34 } 35 while (!b.empty() && !in[b.front()]) 36 { 37 int tmp = b.front(); b.pop(); 38 if (!same(tmp, last)) cnt++; 39 last = tmp; 40 for (int i = 0; i < (int)G[tmp].size(); i++) 41 { 42 int son = G[tmp][i]; 43 if (--in[son] == 0) help(a, b, son); 44 } 45 } 46 rnd++; 47 } 48 return cnt; 49 } 50 int main() 51 { 52 int d, x, y; 53 while (~scanf("%d %d %d", &n1, &n2, &d), n1 + n2 + d) 54 { 55 for (int i = 1; i <= n1 + n2; i++) G[i].clear(); 56 vector<int> in(n1 + n2 + 1, 0); 57 while (d--) 58 { 59 scanf("%d %d", &x, &y); 60 G[y].push_back(x); 61 in[x]++; 62 } 63 queue<int> a, b; 64 for (int i = 1; i <= n1 + n2; i++) 65 { 66 if (!in[i]) help(a, b, i); 67 } 68 printf("%d\n", min(cal(a, b, in, true), cal(a, b, in, false)) + 1); 69 } 70 return 0; 71 }