Codeforces 1545 E. Number of Simple Paths (topo找环 + 计数)

链接: E. Number of Simple Paths

题意:
给一个 n 个点 n 条边 的联通图,求图中的路径数 (1 - 2 和 2 - 1算同一条路径)。

思路:

  1. 由于是 n 个点 n 条边,所以就是一棵树加了一条边,必定存在一个环,所以我们只需要找到这个环上的点,求出每个点有多少个儿子节点(每个点 dfs 一遍就好了),然后就是计数,如果两个点都在环上,或者属于两个不同的子树,那么两点间的路径数就是 2 ,如果属于同一子树路径数就是 1 .
  2. 可以用 topo 找环,每次把度为 1 的点去除,最后留下的点就是环上的点。

代码:

#include<iostream>
#include<cstdio>
#include<map>
#include<math.h>
#include<queue>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
int head[maxn],du[maxn],num,n,T;
int vis[maxn];
ll ans = 0,sum,siz[maxn];
vector< int >vec;
struct node{
    
    
    int to,next;
}e[maxn<<1];
void add(int u,int v){
    
    
    e[num].to = v;
    e[num].next = head[u];
    head[u] = num ++;
}
void topo(){
    
    
    queue< int > que;
    for(int i = 1; i <= n ; i ++){
    
    
        if(du[i] == 1){
    
    
            que.push(i);
        }
    }
    while(que.size()){
    
    
        int u = que.front();
        que.pop();
        for(int i = head[u]; i != -1 ; i = e[i].next){
    
    
            int to = e[i].to;
            du[to] -- ;
            if(du[to] == 1){
    
    
                que.push(to);
            }
        }
    }
}
void dfs(int u,int pre){
    
    
    siz[u] = 1;
    for(int i = head[u]; i != -1 ; i = e[i].next){
    
    
        int v = e[i].to;
        if(v == pre || vis[v]) continue;
        dfs(v , u);
        siz[u] += siz[v];
    }
}
int main(){
    
    
    scanf("%d",&T);
    while(T--){
    
    
        scanf("%d",&n);
        vec.clear();
        ans = sum = 0;
        num = 0;
        for(int i = 1; i <= n ; i ++){
    
    
            head[i] = -1;
            du[i] = siz[i] = vis[i] = 0;
        }
        for(int i = 1,u,v; i <= n ; i ++){
    
    
            scanf("%d%d",&u,&v);
            add(u,v);
            add(v,u);
            du[u]++,du[v]++;
        }
        topo();
        for(int i = 1; i <= n; i ++){
    
    
            if(du[i] >= 2){
    
    
                vec.push_back(i);
                vis[i] = 1;
            }
        }
        for(int i = 1; i <= n; i ++){
    
    
            if(du[i] >= 2){
    
    
                dfs(i , -1);
            }
        }
        ll temp = 0;
        for(auto u : vec){
    
    
            ans += siz[u] * (siz[u] - 1) / 2;
            ans += siz[u] * temp * 2;
            temp += siz[u];
        }
        printf ("%lld\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/hddddh/article/details/110147307