P2746 [USACO5.3]校园网Network of Schools

 1 #include<iostream>
 2 #include<stack>
 3 #include<vector>
 4 #include<set>
 5 #include<algorithm>
 6 using namespace std;
 7 
 8 const int maxn = 10010;
 9 int n;
10 int dfn[maxn]; //第i个点被dfs到次序
11 int low[maxn];    //二叉搜索树上i所在子数上仍在栈中的最小dfn,low[i]相等的点在一个强连通分量中
12 int ind[maxn];
13 bool vis[maxn];
14 stack<int>s;
15 vector<int>to[maxn];
16 set<int>g[maxn];
17 int tot;
18 int cnt;
19 int res[maxn];    //储存强连通分量,res[i]表示点i属于第res[i]个强连通分量
20 int num[maxn];    //第i个强连通分量的点数
21 int ans[2];
22 
23 void tarjan(int x)
24 {
25     dfn[x] = low[x] = ++cnt;
26     s.push(x);
27     vis[x] = true;
28     for (int i = 0; i < to[x].size(); i++)
29     {
30         if (!dfn[to[x][i]])
31         {
32             tarjan(to[x][i]);
33             low[x] = min(low[x], low[to[x][i]]);
34         }
35         else if (vis[to[x][i]])
36         {
37             low[x] = min(low[x], dfn[to[x][i]]);
38         }
39     }
40     if (low[x] == dfn[x])
41     {
42         tot++;
43         while (!s.empty() && s.top() != x)
44         {
45             int t = s.top();
46             res[t] = tot;
47             num[tot]++;
48             vis[t] = false;
49             s.pop();
50         };
51         s.pop();
52         res[x] = tot;
53         num[tot]++;
54         vis[x] = false;
55     }
56 }
57 
58 int main()
59 {
60     cin >> n;
61     for (int i = 1; i <= n; i++)
62     {
63         int t;
64         cin >> t;
65         while (t)
66         {
67             to[i].push_back(t);
68             cin >> t;
69         }
70     }
71     for (int i = 1; i <= n; i++)
72     {
73         if (!dfn[i]) tarjan(i);
74     }
75     for (int i = 1; i <= n; i++)
76     {
77         for (int j = 0; j < to[i].size(); j++)
78         {
79             if (res[i] != res[to[i][j]])
80             {
81                 g[res[i]].insert(res[to[i][j]]);
82                 ind[res[to[i][j]]]++;
83             }
84         }
85     }
86     for (int i = 1; i <= tot; i++)
87     {
88         if (!ind[i]) ans[0]++;
89         if (!g[i].size()) ans[1]++;
90     }
91     if (tot == 1) cout << 1 << endl << 0;
92     else cout << ans[0] << endl << max(ans[0], ans[1]);
93     return 0;
94 }
View Code

 

posted on 2019-10-20 21:04  thjkhdf12  阅读(98)  评论(0)    收藏  举报