UOJ#416. 【APIO2018】铁人两项
原文链接www.cnblogs.com/zhouzhendong/p/UOJ416.html
前言
完了完了SB选手Tarjan写挂。
题解
考虑先Tarjan缩个点双建个圆方树。
然后发现,确定起点和终点后,中间点的可选方案数就是 这条路径上的所有点双 size 之和-2 。
定义原点表示原图中的点,方点表示圆方树中新加入的点。
这个东西可以转化为路径上的方点度数之和减去原点个数。
定义点 x 的权值 d[x] ,当 x 为圆点时 d[x] = -1,否则 d[x] 等于 x 的度数。
设起点终点都是圆点的经过点 x 的路径条数为 c[x],那么点 x 对答案的贡献就是 d[x] * c[x] 。
时间复杂度 $O(n)$。
代码
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define fi first
#define se second
#define real __zzd001
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector <int> vi;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=100005*2;
int n,m,k;
vector <int> e[N],t[N];
LL ans=0;
int dfn[N],low[N],st[N],Time=0,top=0;
void Add_Edge(int x,int y){
t[x].pb(y),t[y].pb(x);
}
int Size;
void Tarjan(int x){
Size++;
dfn[x]=low[x]=++Time;
st[++top]=x;
for (auto y : e[x])
if (!dfn[y]){
Tarjan(y);
low[x]=min(low[x],low[y]);
if (low[y]>=dfn[x]){
Add_Edge(x,++k);
do {
Add_Edge(st[top],k);
} while (st[top--]!=y);
}
}
else
low[x]=min(low[x],dfn[y]);
}
int size[N],d[N];
void dfs(int x,int pre){
size[x]=x<=n;
int v=x<=n?-1:(int)t[x].size();
for (auto y : t[x])
if (y!=pre){
dfs(y,x);
ans+=2LL*v*size[x]*size[y];
size[x]+=size[y];
}
ans+=2LL*v*size[x]*(Size-size[x]);
}
int main(){
n=read(),m=read(),k=n;
For(i,1,m){
int x=read(),y=read();
e[x].pb(y),e[y].pb(x);
}
For(i,1,n)
if (!dfn[i])
Size=0,Tarjan(i),dfs(i,0);
cout<<ans<<endl;
return 0;
}
UOJ#416. 【APIO2018】铁人两项的更多相关文章
- [APIO2018]铁人两项 --- 圆方树
[APIO2018] 铁人两项 题目大意: 给定一张图,问有多少三元组(a,b,c)(a,b,c 互不相等)满足存在一条点不重复的以a为起点,经过b,终点为c的路径 如果你不会圆方树 ------- ...
- [APIO2018]铁人两项——圆方树+树形DP
题目链接: [APIO2018]铁人两项 对于点双连通分量有一个性质:在同一个点双里的三个点$a,b,c$,一定存在一条从$a$到$c$的路径经过$b$且经过的点只被经过一次. 那么我们建出原图的圆方 ...
- [APIO2018]铁人两项 [圆方树模板]
把这个图缩成圆方树,把方点的权值设成-1,圆点的权值设成点双的size,算 经过这个点的路径的数量*这个点的点权 的和即是答案. #include <iostream> #include ...
- [APIO2018]铁人两项(圆方树)
过了14个月再重新看这题,发现圆方树从来就没有写过.然后写了这题发现自己APIO2018打铁的原因竟然是没开long long,将树的部分的O(n)写挂了(爆int),毕竟去年APIO时我啥都不会,连 ...
- 2019.03.29 bzoj5463: [APIO2018] 铁人两项(圆方树+树形dp)
传送门 题意简述:给你一张无向图,问你满足存在从a−>b−>ca->b->ca−>b−>c且不经过重复节点的路径的有序点对(a,b,c)(a,b,c)(a,b,c) ...
- LOJ.2587.[APIO2018]铁人两项Duathlon(圆方树)
题目链接 LOJ 洛谷P4630 先对这张图建圆方树. 对于S->T这条(些)路径,其对答案的贡献为可能经过的所有点数,那么我们把方点权值设为联通分量的大小,可以直接去求树上路径权值和. 因为两 ...
- [BZOJ5463][APIO2018]铁人两项:Tarjan+圆方树
分析 根据题目中的要求,从\(s\)出发前往\(f\)一定可以,并且只可能经过这两个结点所在的点双连通分量和它们之间的点双连通分量,因此切换点\(c\)只能从这些点中选取. 建出圆方树后,因为圆方树上 ...
- 洛谷P4630 [APIO2018]铁人两项 [广义圆方树]
传送门 又学会了一个新东西好开心呢~ 思路 显然,假如枚举了起始点\(x\)和终止点\(y\),中转点就必须在它们之间的简单路径上. 不知为何想到了圆方树,可以发现,如果把方点的权值记为双联通分量的大 ...
- [BZOJ5463] [APIO2018] 铁人两项
题目链接 LOJ. BZOJ. Solution 先建圆方树. 我们考虑暴力,枚举一个点对,我们枚举的点都是圆点,然后统计中间那个点可以取的位置的数量,加起来就是答案. 那么怎么统计呢,我们对于每个点 ...
- LOJ2587:[APIO2018]铁人两项——题解
https://loj.ac/problem/2587#submit_code (题面来自LOJ) 考试时候发觉树很可做,并且写了一个dp骗到了树的分. 苦于不会圆方树……现在回来发现这题还是很可做的 ...
随机推荐
- vue(初探预渲染)
---恢复内容开始--- 一.前言 1.简介预渲染 2.案例演示(不配置预渲染) 3.配置预渲染, 二.主要内容 1.简 ...
- 微信小程序绘制分享图
微信小程序绘制分享图例子: demo下载地址:https://gitee.com/v-Xie/wxCanvasShar 大致代码会再以下说明 实际开发项目: 基础知识点: 了解canvas基础知识 w ...
- Java基础--面向对象编程1(类与对象)
1.类(class)的定义 类是对一组具有相同特征和行为的对象的抽象描述. 在程序中,引入类的概念,就是为了快速生成更多的具有相同特性和行为的事物. 2.对象(object)的定义 对象是类的具体实现 ...
- MySQL 死锁场景
SESSION 1 SESSION 2 SESSION 3 START TRANSACTION START TRANSACTION START TRANSACTION INSERT INS ...
- 079、监控利器 sysdig (2019-04-26 周五)
参考https://www.cnblogs.com/CloudMan6/p/7646995.html sysdig 是一个轻量级的系统监控工具,同时他还原生支持容器.通过sysdig我们可以近距离 ...
- How to delete VSTS Project
Buiding is so easy , Where is deleting ? C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7 ...
- count
select deptno as 部门,count(*) as 人数from emp group by deptno; --统计各个部门的人数
- MySQL中使用group_concat()函数数据字符过长报错的问题解决方法
最近在办公软件项目,在开发权限指标遇到一个问题:我们系统的一些逻辑处理是用存储过程实现的,但是有一天客户反馈说权限指标分配报错,查了分配的权限数据牵扯到的数据权限基础资源,没有问题.权限指标分配的存储 ...
- STL--hashtable
hashtable使用开链的方式,解决元素个数大于array容量的问题. 当两个不同元素hash得到相同的hash值时,此时我们使用bucket list来链接连个元素. hashtable迭代器必须 ...
- C++变量/函数命名规范
## 参照Google C++编程规范之变量命名 1. 变量 变量名一律小写,单词间以下划线相连.类的成员变量以下划线结尾. 普通变量命名 举例: string window_name; // OK ...