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

7 篇文章 0 订阅
1 篇文章 0 订阅

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

Problem Description

You are given an undirected graph consisting of n vertices and n edges. It is guaranteed that the given graph is connected (i. e. it is possible to reach any vertex from any other vertex) and there are no self-loops and multiple edges in the graph.
Your task is to calculate the number of simple paths of length at least 1 in the given graph. Note that paths that differ only by their direction are considered the same (i. e. you have to calculate the number of undirected paths). For example, paths [1,2,3] and [3,2,1] are considered the same.
You have to answer t independent test cases.
Recall that a path in the graph is a sequence of vertices v1,v2,…,vk such that each pair of adjacent (consecutive) vertices in this sequence is connected by an edge. The length of the path is the number of edges in it. A simple path is such a path that all vertices in it are distinct.

Input

The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.
The first line of the test case contains one integer n (3≤n≤2⋅105) — the number of vertices (and the number of edges) in the graph.
The next n lines of the test case describe edges: edge i is given as a pair of vertices ui, vi (1≤ui,vi≤n, ui≠vi), where ui and vi are vertices the i-th edge connects. For each pair of vertices (u,v), there is at most one edge between u and v. There are no edges from the vertex to itself. So, there are no self-loops and multiple edges in the graph. The graph is undirected, i. e. all its edges are bidirectional. The graph is connected, i. e. it is possible to reach any vertex from any other vertex by moving along the edges of the graph.
It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output

For each test case, print one integer: the number of simple paths of length at least 1 in the given graph. Note that paths that differ only by their direction are considered the same (i. e. you have to calculate the number of undirected paths).

Example

input
3
3
1 2
2 3
1 3
4
1 2
2 3
3 4
4 2
5
1 2
2 3
1 3
2 5
4 3
output
6
11
18

Note

Consider the second test case of the example. It looks like that:
There are 11 different simple paths:
[1,2];
[2,3];
[3,4];
[2,4];
[1,2,4];
[1,2,3];
[2,3,4];
[2,4,3];
[3,2,4];
[1,2,3,4];
[1,2,4,3].


题意

给定一个n个点n条边的图,求有多少条不同的路径。

思路

n个点n条边,可以知道是基环树,整个图有且只有一个环,环上连接着若干棵树。
我们可以发现,只有路径上的两个端点都在同一棵树上时,该两点间的路径条数为1,否则均为2.
所以我们将这部分减去即可。设该树上的点数为m,即减去m*(m-1)。


Code

#include <bits/stdc++.h>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <iostream>
#include <queue>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> VI;
typedef vector<ll> VLL;
typedef vector<VI> VII;
typedef vector<VII> VIII;
typedef pair<int, int> PII;

#define rep(i,a,b) for(int i = (a); i <= (b); i ++)
#define per(i,a,b) for(int i = (a); i >= (b); i --)
#define mkp(a,b) make_pair(a,b)

//#define __int128 ll

const int N = 2e5 + 5;
//const int M = 30 + 5;
const int INF = 0x3f3f3f3f;
const double EPS = 1e-9;
const double EPSS = 1e-12;
//const double PI = acos(-1);
//const double PI = 3.14;
const ll MOD = 1e9 + 7;
//const ll MOD = 998244353;
//const ll MOD = 233333333;
//const int dx[] = {-1, 1, 0, 0};
//const int dy[] = {0, 0, -1, 1};

//const int dx[] = { 1, 0, 0,-1};
//const int dy[] = { 0,-1, 1, 0};

VI G[N];

int fa[N];        //dfs时的父亲
int dfn[N], idx;  //访问的时间
int loop[N], cnt; //环

int vis[N];

void get_loop(int u)
{
    dfn[u] = ++ idx;
    int sz = G[u].size();
    for (int i = 0; i < sz; i ++)
    {
        int v = G[u][i];
        if(v == fa[u])
            continue ;
        if(dfn[v])
        {
            if(dfn[v] < dfn[u])
                continue ;
            loop[++ cnt] = v;
            for ( ; v != u; v = fa[v])
                loop[++ cnt] = fa[v];
        }
        else
            fa[v] = u, get_loop(v);
    }
}

int dfs(int p)
{
    vis[p] = 1;
    int ret = 1;
    int sz = G[p].size();
    rep(i,0,sz-1)
    {
        if(vis[G[p][i]] == 1)
            continue;
        ret += dfs(G[p][i]);
    }
    return ret;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d", &n);
        rep(i,1,n) vis[i] = fa[i] = dfn[i] = 0;
        rep(i,1,n) G[i].clear();
        cnt = idx = 0;
        rep(i,1,n)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        get_loop(1);
        rep(i,1,cnt) vis[loop[i]] = 1;
        ll ans = 1ll * n * (n-1);
        rep(i,1,cnt)
        {
            ll num = dfs(loop[i]);
            ans -= 1ll * num * (num-1)/2;
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值