TZOJ 6558: 城镇封锁(tarjan割点)

描述

Byteotia 城市有 n 个城镇,m 条双向道路。每条道路连接两个不同的城镇,没有重复的道路,所有城镇连通。

输出 n 个数,代表如果把第 i 个点去掉,将有多少对点不能互通。

输入

输入 n,m 及 m 条边(n≤10^5,m≤5×10^5 )。

输出

输出 n 个数,代表如果把第 i 个点去掉,将有多少对点不能互通。

样例输入

5 5
1 2
2 3
1 3
3 4
4 5

样例输出

8
8
16
14
8

思路(tarjan)

 

题目有规律:如果去除的不是割点,答案为2*(n-1),如果是割点,则是各个子集大小乘以剩余集合的大小,再求和,加上n-1
所以重点是记录各个子集的大小,因为与生成树不一样,这里有回路,所以应该用两个参数记录


【注意】

去掉某一点后产生的点对主要有三种:

1、u点和其他的点(n-1)

2、u点下的各个子树内的点与其他的点(不含u)

3、u点下的所有子树外的点(可以理解为父亲方向上的子树,但包含于u点同双联通的点)到其他的点

【代码存在的遗留问题】

对于  sum[u]+=(n-res-1)*res+(n-1)   

不知道为什么这里要(n-res-1),这个 -1 就很奇怪,但是答案对了 

AC代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+10,INF=0x3f3f3f3f;
int n,ans,m,t,idx;
vector<int>vec[N];
int dfn[N]={0},low[N]={0},s[N]={0};
ll sum[N]={0};
void tarjan(int u,int pre){
    low[u]=dfn[u]=++idx;
    s[u]=1;//存子树节点数量 
    int num=0;
    ll res=0;//res已用块的节点总数 
    for(int i=0;i<vec[u].size();++i){
        int ne=vec[u][i];
        if(!dfn[ne]){
            num++;
            tarjan(ne,u);
            low[u]=min(low[u],low[ne]);
            s[u]+=s[ne];//记录u的子树节点数量 
            if((low[ne]>=dfn[u]&&pre!=u)||(u==pre&&num>=2)){
    //x的子树ne能提供的个数 * 前面也就提供的同属x子树的个数和 
                sum[u]+=s[ne]*res;//所有子树的边 
                res+=s[ne];//加上ne的节点数 
            }
        }
        else
            low[u]=min(low[u],dfn[ne]);
    }
    //不知道为什么这里要(n-res-1),这个-1就很奇怪,但是答案对了 
    sum[u]+=(n-res-1)*res+(n-1);
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i){
        int u,v;
        scanf("%d%d",&u,&v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    } 
    for(int i=1;i<=n;++i)
        if(!dfn[i])
            tarjan(i,i);
    for(int i=1;i<=n;++i){
        if(i>1) printf("\n");
        printf("%lld",sum[i]*2);
    }
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值