zoukankan      html  css  js  c++  java
  • Luogu 2812 校园网络

    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
    ", ans1);
    76     if(col_num == 1) return printf("0
    "), 0;
    77     for(int i = 1; i <= col_num; ++i)
    78         if(!chu[i]) ans2++;
    79     printf("%d
    ", max(ans1, ans2));
    80 }
    View Code
  • 相关阅读:
    AcWing 1081. 度的数量
    CF584D Dima and Lisa
    [ABC130F] Minimum Bounding Box
    AT4289 [ABC133E] Virus Tree 2
    Arc of Dream HDU
    Reading comprehension HDU
    【洛谷 1541】乌龟棋
    【洛谷 4880】抓住czx
    【洛谷 1525】关押罪犯
    【洛谷 1040】加分二叉树
  • 原文地址:https://www.cnblogs.com/cychester/p/9629789.html
Copyright © 2011-2022 走看看