题目描述
Byteotia城市有n个 towns m条双向roads. 每条 road 连接 两个不同的 towns ,没有重复的road. 所有towns连通。
输入
输入n<=100000 m<=500000及m条边
输出
输出n个数,代表如果把第i个点去掉,将有多少对点不能互通。
样例输入
5 5
1 2
2 3
1 3
3 4
4 5
样例输出
8
8
16
14
8

易得是割点板子题
对于图上每个割点(非割点无法对答案进行贡献)而言,设其将原连通图分为k个不相连通的子图,第i个子图元素个数为x[i],
于是该割点对答案的贡献为Σx[i]*x[j](i!=j,i,j∈x)。
同时观察样例我们可以知道,所谓不能互通的点具有顺序(比如(1,2)和(2,1))。
我们又知道,对于tarjan算法中一棵搜索树,一共包含两个部分:
(1)由割点引出的很多棵子树。
(2)与割点父亲相连通的所有点。
(3)割点本身。

其中绿、蓝、黄分别是第1、2、3部分。
为了方便起见,我们在下文中将这三部分用1、2和3表示。
所以我们可以将答案分成以下几个部分:
(1)搜索树上每棵由根节点引出的子树向其它点连通的点对(包括了1内部的点对、1向2连通的点对、1向3连通的点对)
(2)与割点父亲连通的点向割点连通的点对(2向3)
(3)割点向所有点连通的点对(3向1、2)
(4)与割点父亲连通的点向根节点子树连通的点对(2向1)
第一部分很容易处理,我们设每棵根节点prev向外引出的子树元素个数为subtree[prev],则其余点的个数共(n-subtree[prev])个,
于是我们可以将subtree[prev]*(n-subtree[prev])贡献到答案ans[x]中;(注意x是每个prev的父亲)
第二部分,我们设所有割点引出的子树(不包含割点自己)元素个数总和为sum,因为每次讨论的割点只有一个,其余点就有(n-sum-1)个,
则我们可以将(n-sum-1)贡献到答案ans[x]中;
第三部分更容易处理,因为每次讨论的割点只有一个,其它点有(n-1)个,于是我们将(n-1)贡献到答案中;
第四部分,我们将sum*(n-sum-1)贡献到答案中。
于是,对于每个割点x,有ans[x]=∑subtree[prev]*(n-subtree[prev])+(n-sum-1)+(n-1)+sum*(n-sum-1)=∑subtree[prev]*
(n-subtree[prev])+(n-sum-1)+(sum+1)*(n-sum-1);
对于非割点x,有ans[x]=2*(n-1)(只有割点本身受影响)。

关于统计subtree数组,我们每次进入函数时将subtree[x]置为1(表示这棵树只有根节点一个节点),然后在tarjan(y)回溯时令
tarjan[x]=tarjan[y]+1即可。
这种类似前缀和的树上技巧需要我们学习。
上代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int head[],num,n,m,cut[],dfn[],subtree[],low[],root,cnt;
long long ans[];
struct edge
{
int u,v,nxt;
}e[];
void add(int u,int v)
{
e[num].u=u,e[num].v=v;
e[num].nxt=head[u],head[u]=num++;
}
void tarjan(int x,int in_edge)/*这里用到一个技巧,对于每个点x记录上一个点搜索到x的边的编号,因为是无向图,则其反向边的编号必为in_edge^1(可以自己算一下),但需要注意邻接表必须从0开始存*/
{
dfn[x]=low[x]=++cnt;
subtree[x]=;
int flag=,sum=;
for(int st=head[x];st!=-;st=e[st].nxt)
{
int y=e[st].v;
if(!dfn[y])
{
tarjan(y,st);
subtree[x]+=subtree[y];
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
sum+=subtree[y];
ans[x]+=(long long)subtree[y]*(n-subtree[y]);//(1)
flag++;
if(x!=root||flag>)cut[x]=;
}
}
else if(st!=(in_edge^))//注意这个地方,异或运算的优先级低于比较,所以必须加括号
{
low[x]=min(low[x],dfn[y]);
}
}
if(cut[x]) {
ans[x]+=(long long)(n-sum-)*(sum+)+(n-);//(2)(3)(4)
}
else ans[x]=*(n-);//不是割点则不影响其它点
}
int main()
{
memset(head,-,sizeof head);
scanf("%d%d",&n,&m);
int a,b;
for(int i=;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}//注意是无向图
root=;
for(int i=;i<=n;i++)//处理不连通图
if(!dfn[i])root=i,tarjan(i,-);
for(int i=;i<=n;i++)printf("%lld\n",ans[i]);//注意不开longlong会炸
return ;
}

2019暑假集训 BLO的更多相关文章

  1. 2019暑假集训 Intervals

    题目描述 给定n个闭区间[ai,bi]和n个整数ci.你需要构造一个整数集合Z,使得对于任意i,Z中满足ai<=x<=bi的x不少于ci个.求Z集合中包含的元素个数的最小值.  输入 第一 ...

  2. 2019暑假集训 windy数

    题目描述 Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为2的正整数被称为 Windy 数. Windy 想知道,在A和B之间,包括A和B,总共有多少个 Windy 数? 输 ...

  3. 2015UESTC 暑假集训总结

    day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...

  4. STL 入门 (17 暑假集训第一周)

    快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...

  5. 暑假集训Day2 互不侵犯(状压dp)

    这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...

  6. 暑假集训Day1 整数划分

    题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...

  7. 2013ACM暑假集训总结-致将走上大三征途的我

    回想起这个暑假,从开始与雄鹰一起的纠结要不要进集训队,与吉吉博博组队参加地大邀请赛,害怕进不了集训队.当时激励我月份开始接触的,记得当时在弄运动会来着,然后就问了雄鹰一些输入输出的东西,怀着满心的期待 ...

  8. [补档]暑假集训D5总结

    %dalao 今天又有dalao来讲课,讲的是网络流 网络流--从入门到放弃:7-29dalao讲课笔记--https://hzoi-mafia.github.io/2017/07/29/27/   ...

  9. [补档]暑假集训D1总结

    归来 今天就这样回来了,虽然心里极其不想回来(暑假!@#的只有一天啊喂),但还是回来了,没办法,虽然不喜欢这个地方,但是机房却也是少数能给我安慰的地方,心再累,也没有办法了,不如好好集训= = %da ...

随机推荐

  1. Codility--- TapeEquilibrium

    Task description A non-empty zero-indexed array A consisting of N integers is given. Array A represe ...

  2. asp.net mvc+jquery easyui开发实战教程之网站后台管理系统开发3-登录模块开发

    进行本文之前需要在数据库用户表里面增加一条用户数据,直接手动添加即可,未安全考虑密码一定要使用Md5加密后的,这里提供666666的Md5密文为(c831b04de153469d),本文完成登录模块的 ...

  3. ElasticSearch2.3.1环境搭建哪些不为人知的坑

    首先说明一点,大家最好不要用什么尝鲜版,用比稳定版就好了,要不麻烦不断,另外出了问题,最好去官网,或者google搜索,因为这样靠谱些,要不现在好多都是低版本的,1.4的什么的,结果按照安装,多少情况 ...

  4. 03- 基本的SQL语句介绍

    01 库的操作新增库create database db1 charset utf8; # 由于在my.ini中已经配置了字符集,所以,charset utf8可以不写 查库# 查看当前创建的数据库s ...

  5. 由django请求生命周期延伸出的知识点大总结

    django项目搭建见: https://www.cnblogs.com/dongxixi/p/10981577.html django请求生命周期图: 由浏览器发起请求开始 知识点1: 浏览器与服务 ...

  6. Django中信号signals简单使用

    在平时的开发过程中,我们会遇到一些特殊的应用场景,如果你想要在执行某种操作之前或者之后你能够得到通知,并对其进行一些你想要的操作时,你就可以用Django中的信号(signals).Django 提供 ...

  7. JS数据结构第四篇 --- 栈

    一.什么是数据结构栈 在数据结构中有一个栈结构,在内存空间中也有一个栈空间,这两个”栈“是两个不同的概念.这篇我们说的是数据结构中的栈.栈是一种特殊的线性表,特殊性在哪?就是只能在栈顶进行操作,往栈顶 ...

  8. Liunx 安装 Nessus

    Liunx 安装 Nessus   啥子是Nessus 它是一款系统漏洞扫描与分析软件,可以扫描服务器存在哪些漏洞,页面简介美观,非常Nice. 获取激活码 首先访问如下网站 https://www. ...

  9. Linux系统:centos7下安装Jdk8、Tomcat8、MySQL5.7环境

    一.JDK1.8 环境搭建 1.上传文件解压 [root@localhost mysoft]# tar -zxvf jdk-8u161-linux-x64.tar.gz [root@localhost ...

  10. 2. 2.1查找命令——linux基础增强,Linux命令学习

    2.1.查找命令 grep命令 grep 命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并 把匹配的行打印出来. 格式: grep [option] pattern [file] 可使用 ...