Luogu 2812 校园网络 - Tarjan

Description

给出一个有向图, 要求出至少从哪几个点出发, 能不漏地经过所有节点。

再求出至少加几条边, 才能使图变成一个强联通分量

Solution

求出所有强联通分量, 形成一个有向无环图, 第一问题就是求出有多少强联通分量的入度为 $0$ 

第二个问题就是求出 入度为$0 $和 出度为$0$  的强联通分量的数量  的 最大值, 想象一下就可以了。

在整个图都是强联通分量下, 第二个问题答案为 $0$。

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define rd read()
 5 #define rep(i,a,b) for(int i = (a); i <= (b); ++i)
 6 #define per(i,a,b) for(int i = (a); i >= (b); --i)
 7 using namespace std;
 8 
 9 const int N = 10500;
10 const int M = 6e6;
11 
12 int head[N], tot;
13 int col[N], col_num, size[N];
14 int n, dfn[N], low[N], cnt, vis[N];
15 int st[N], tp, ans1, ans2;
16 int chu[N], ru[N];
17 
18 struct edge {
19     int nxt, to, fr;
20 }e[M];
21 
22 int read() {
23     int X = 0, p = 1; char c = getchar();
24     for(; c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
25     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
26     return X * p;
27 }
28 
29 void add(int u, int v) {
30     e[++tot].to = v;
31     e[tot].nxt = head[u];
32     e[tot].fr = u;
33     head[u] = tot;
34 }
35 
36 void tarjan(int u) {
37     dfn[u] = low[u] = ++cnt;
38     st[++tp] = u;
39     vis[u] = 1;
40     for(int i = head[u]; i; i = e[i].nxt) {
41         int nt = e[i].to;
42         if(!dfn[nt]) tarjan(nt), low[u] = min(low[u], low[nt]);
43         else if(vis[nt]) low[u] = min(low[u], dfn[nt]);
44     }
45     if(dfn[u] == low[u]) {
46         col_num++;
47         for(; tp;) {
48             int nt = st[tp--];
49             vis[nt] = 0;
50             col[nt] = col_num;
51             if(nt == u) break;
52         }
53     }
54 }
55 
56 int main()
57 {
58     n = rd;
59     for(int i = 1; i <= n; ++i) {
60         for(; ;) {
61             int x = rd;
62             if(!x) break;
63             add(i, x);
64         }
65     }
66     for(int i = 1; i <= n; ++i) 
67         if(!dfn[i]) tarjan(i);
68     for(int i = 1; i <= tot; ++i) {
69         int x = e[i].fr, y = e[i].to;
70         if(col[x] == col[y]) continue;
71         ru[col[y]]++; chu[col[x]]++;
72     }
73     for(int i = 1; i <= col_num; ++i) 
74         if(!ru[i]) ans1++;
75     printf("%d\n", ans1);
76     if(col_num == 1) return printf("0\n"), 0;
77     for(int i = 1; i <= col_num; ++i)
78         if(!chu[i]) ans2++;
79     printf("%d\n", max(ans1, ans2));
80 }
View Code

猜你喜欢

转载自www.cnblogs.com/cychester/p/9629789.html
今日推荐