Gym 100342I Travel Agency (Tarjan)

本文介绍了一种求解点双连通分量的算法,并通过实例代码详细解析了如何利用该算法来解决特定问题。核心思路在于通过深度优先搜索(DFS)找到图中的割点,进而统计割点分割的各个连通分量节点数量。

题意读懂了就好做了,就是求一下点双连通分量。维护一下一颗子树的结点数,对于一个结点当u是割点的时候,

统计一下u分割的连通分量v,每得到一个连通分量的结点数cnt(v)和之前连通分量结点数sum相乘一下就好。最后加一下和u的子树上的连通分量总数和其它的结点的乘积。

B,C中其中一者可以是A,所有最后还要加上n-1。

补下以前的题

#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn = 20005;
vector<int> G[maxn];
#define PB push_back

int dfn[maxn],low[maxn],dfs_clock,ans[maxn],cnt[maxn];

void tarjan(int u,int fa = -1)
{
    dfn[u] = low[u] = ++dfs_clock;
    cnt[u] = 1; ans[u] = 0;
    int sum = 0;
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];
        if(!dfn[v]){
            tarjan(v,fa);
            if(low[v]>=dfn[u]){
                ans[u] += sum*cnt[v];
                sum += cnt[v];
            }
            low[u] = min(low[v],low[u]);
            cnt[u] += cnt[v];
        }else if(v != fa && dfn[v] < dfn[u] ) { low[u] = min(low[u],dfn[v]); }
    }
    ans[u] += (n-sum-1)*sum;

}

int main()
{
    freopen("travel.in","r",stdin);
    freopen("travel.out","w",stdout);
    cin>>n>>m;
    for(int i = 0; i < m; i++){
        int u,v; scanf("%d%d",&u,&v);
        G[u].PB(v); G[v].PB(u);
    }
    tarjan(1);
    for(int i = 1; i <= n; i++) printf("%d\n",ans[i]+n-1);
    return 0;
}

 

转载于:https://www.cnblogs.com/jerryRey/p/4770915.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值