题意:每头牛都想成为牛群中的红人。给N头牛的的牛群和M个有序对(A,B)。(A,B)表示牛A认为B是红人。该关系具有传递性,所以如果牛A认为B是红人,牛B认为牛C是红人,那么牛A也认为牛C是红人。不过,给定的有序对中可能包含(A,B)和(B,C),但不包含(A,C)。求被其他牛认为是红人的总数。
思路:方法是是找到拓扑排序最后的那个强连通分量在统计他是不是能访问到所有的结点就OK了。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <cstring> 6 #include <algorithm> 7 #include <queue> 8 #include <stack> 9 #include <vector> 10 #define MP(a, b) make_pair(a, b) 11 #define PB(a) push_back(a) 12 13 using namespace std; 14 15 typedef long long ll; 16 typedef pair<int ,int> pii; 17 typedef pair<unsigned int, unsigned int> puu; 18 typedef pair<int ,double> pid; 19 typedef pair<ll, int> pli; 20 21 const int INF = 0x3f3f3f3f; 22 const double eps = 1e-6; 23 const int LEN = 10000+10; 24 int vis[LEN], n, m, cmp[LEN]; 25 vector<int> Map[LEN], rMap[LEN], vs; 26 27 void dfs(int v) 28 { 29 vis[v] = 1; 30 for(int i=0; i<Map[v].size(); i++){ 31 if(!vis[Map[v][i]])dfs(Map[v][i]); 32 } 33 vs.PB(v); 34 } 35 36 void rdfs(int v, int k) 37 { 38 vis[v] = 1; 39 cmp[v] = k; 40 for(int i=0; i<rMap[v].size(); i++){ 41 if(!vis[rMap[v][i]])rdfs(rMap[v][i], k); 42 } 43 } 44 45 int scc() 46 { 47 memset(vis, 0, sizeof vis); 48 vs.clear(); 49 for(int i=1; i<=n; i++){ 50 if(!vis[i])dfs(i); 51 } 52 memset(vis, 0, sizeof vis); 53 int k = 0; 54 for(int i=vs.size()-1; i>=0; i--){ 55 if(!vis[vs[i]])rdfs(vs[i], k++); 56 } 57 return k; 58 } 59 60 int main() 61 { 62 // freopen("in.txt", "r", stdin); 63 64 int a, b; 65 while(scanf("%d%d", &n, &m)!=EOF){ 66 for(int i=0; i<LEN; i++)Map[i].clear(); 67 for(int i=0; i<LEN; i++)rMap[i].clear(); 68 for(int i=0; i<m; i++){ 69 scanf("%d%d", &a, &b); 70 Map[a].PB(b); 71 rMap[b].PB(a); 72 } 73 int num = scc(), ans = 0, u = 0; 74 for(int i=1; i<=n; i++)if(cmp[i] == num-1){u = i;ans++;} 75 memset(vis, 0, sizeof vis); 76 rdfs(u, 0); 77 for(int i=1; i<=n; i++)if(!vis[i])ans = 0; 78 printf("%d\n", ans); 79 } 80 return 0; 81 }