题解

1 条题解

  • 1
    @ 2017-05-25 22:53:47

    对于每一个点双联通分量,如果它与两个及以上割点相连,则不需要修建逃生出口,因为其一定可以通过其他割点走到其他逃生出口。如果它只与一个割点相连,则一定需要修建一个逃生出口。

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    using namespace std;
    
    const int maxn = 505;
    struct edge {
        int to, next;
    }e[maxn * 2];
    int m, n, h[maxn], tot;
    int dfn[maxn], low[maxn], Time;
    int vis[maxn];
    bool iscut[maxn];
    long long ans1, ans2;
    
    inline void add(int u, int v)
    {
        e[++tot] = (edge) {v, h[u]};
        h[u] = tot;
    } 
    
    inline void chkmax(int &a, int b)
    {
        if(a < b) a = b;
    }
    
    inline void chkmin(int &a, int b)
    {
        if(a > b) a = b;
    }
    
    int root;
    
    void tarjan(int u, int fa)
    {
        dfn[u] = low[u] = ++Time;
        vis[u] = 1;
        int child = 0;
        for(int i = h[u]; i; i = e[i].next) {
          int v = e[i].to;
          if(v == fa) continue;
          if(!dfn[v]) {
            child++; tarjan(v, u);
            chkmin(low[u], low[v]);
            if(u == root && child >= 2) iscut[u] = true;
            else if(u != root && dfn[u] <= low[v]) iscut[u] = true;
          }else if(vis[v] == 1) chkmin(low[u], dfn[v]);
        }
        if(u == fa && child == 1) iscut[u] = false;
        vis[u] = 2;
    }
    
    int size, sum, now;
    void dfs(int u)
    {
        vis[u] = now; size++;
        for(int i = h[u]; i; i = e[i].next)
          if(!vis[e[i].to] && !iscut[e[i].to]) dfs(e[i].to);
          else if(vis[e[i].to] != now && iscut[e[i].to]) vis[e[i].to] = now, sum++;
    }
    
    int main()
    {
        int i, u, v, Case = 0;
        while(scanf("%d", &m) == 1 && m) {
          memset(h, 0, sizeof(h));
          memset(dfn, 0, sizeof(dfn));
          memset(vis, 0, sizeof(vis));
          memset(iscut, 0, sizeof(iscut));
          tot = n = Time = 0;
          for(i = 1; i <= m; i++) {
            scanf("%d%d", &u, &v);
            add(u, v); add(v, u);
            chkmax(n, u); chkmax(n, v);
          }
          for(i = 1; i <= n; i++)
            if(!dfn[i]) root = i, tarjan(i, i);
          ans1 = 0; ans2 = 1;
          memset(vis, 0, sizeof(vis));
          for(i = 1; i <= n; i++)
            if(!vis[i] && !iscut[i]) {
              now++; size = sum = 0; dfs(i);
              if(sum == 1) ans1++, ans2 *= size;
            }
          if(ans1 == 0) ans1 = 2, ans2 = n * (n - 1) / 2;
          printf("Case %d: %lld %lld\n", ++Case, ans1, ans2);
        }
        return 0;
    }
    
    

    ps:如果这道题为非连通图则我的代码还有错误,但并没有这样的数据,所以我开开心心的AC啦

  • 1

信息

难度
9
分类
(无)
标签
递交数
8
已通过
4
通过率
50%
被复制
1
上传者