zoukankan      html  css  js  c++  java
  • E. Number of Simple Paths(基环树 + 思维)

    Codeforces Round #686 (Div. 3)E. Number of Simple Paths

    题意

    给你n个点n条边的图,让你求树上的简单路径数。

    简单路径:从a->b的方法,需要注意的是1->2>3,3->2->1算一种

    思路

    显然建成后的图是一棵树多了一条边,这种图又叫环基树。

    从下图开始分析该题:

    在这里插入图片描述

    我们假设这个环的每一个点都是一棵树,我们建图。

    在每个以环上的点为根的树上的任意两个点只有(C_n^2)的取法

    其他的任意两个点间的取法都是有两种路径共计(C_n^2 * 2)

    我们先假设任意两个点间都有两种到达方法那么,(ans = C_n^2)

    然后我们再减去只有一种方法的路径,即为所求。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    //#define int long long
    const int maxn = 2e5 + 10;
    int deg[maxn], bfs[maxn];
    vector<int>edge[maxn];
    
    int f[maxn], num[maxn];
    void init(int n) {
        for (int i = 1; i <= n; ++i) {
            f[i] = i; num[i] = 1;
        }
    }
    
    int find(int x) {
        return f[x] == x ? x : f[x] = find(f[x]);
    }
    
    bool Union(int x, int y) {
        int fx = find(x);
        int fy = find(y);
        if (fx == fy) return 0;
        if (num[fx] > num[fy]) swap(fx, fy);
        num[fy] += num[fx];
        f[fx] = fy;
        return 1;
    }
    
    bool is_root(int x) {
        return f[x] == x ? 1 : 0;
    }
    
    void solve() {
        int n; cin >> n;
        init(n);
        for (int i = 1; i <= n; ++i) {
            deg[i] = 0; edge[i].clear();
        }
        for (int i = 1; i <= n; ++i) {
            int u, v; cin >> u >> v;
            edge[u].push_back(v);
            edge[v].push_back(u);
            ++deg[u]; ++deg[v];
        }
        int cnt = 0;
        for (int i = 1; i <= n; ++i)
            if (deg[i] == 1) {
                bfs[++cnt] = i;
                --deg[i];
            }
        for (int i = 1; i <= cnt; ++i) {
            int u = bfs[i];
            for (auto v : edge[u]) {
                --deg[v];
                Union(u, v);
                if (deg[v] == 1) {
                    bfs[++cnt] = v;
                }
            }
        }
        LL ans = n * (n  - 1LL);
        for (int i = 1; i <= n; ++i) {
            if (is_root(i)) {
                ans -= num[i] * (num[i] - 1LL) / 2;
            }
        }
        cout << ans << endl;
    }
    
    
    signed main() {
        int T; cin >> T;
        while (T--) {
            solve();
        }
    }
    
  • 相关阅读:
    要如何用[ZT]sendmessage來切換PageControl1 的TabSheet2呢
    Delphi 常用API 函数
    [ZT]如何得到其他程序的Richedit中的RTF数据
    转帖一篇关于DELPHI调试的文章AQTime
    讀取股票資料檔與指標計算方法之封裝
    GC的三代回收机制
    SQL语句的解析过程
    .Net 垃圾回收机制整理
    美国人吃了交通罚单怎么办?
    Ihttphandler,Ihttpmodule
  • 原文地址:https://www.cnblogs.com/waryan/p/14038085.html
Copyright © 2011-2022 走看看