LOJ2587:[APIO2018]铁人两项——题解
https://loj.ac/problem/2587#submit_code

(题面来自LOJ)
考试时候发觉树很可做,并且写了一个dp骗到了树的分。
苦于不会圆方树……现在回来发现这题还是很可做的!
先套路套圆方树,然后思考路径条数如何计算。
一个显然的想法:从一个点双-> 一个点双->……-> 一个点双,条数没准就是每个点双的大小!
于是我们能够想到方点的权值为点双的大小。
当然注意到我们选择的起点/终点以及每个点双之间相邻的切点只能走一次,为了去重,我们把圆点权值设为-1。
则任取起点s,终点t的情况就是s->t的路径上所有点的权值和。
当然此时我们可以用dp做,但是我当时的代码没拷于是现在我也忘了怎么做了,我们换一种大家普遍(我看其他人代码)的一种方法。
我们求出来每个点u,有多少条路径通过它即可,具体dp可以看我的代码注释。
以及注意这题每个结点之间至多有一条,而不是至少!坑死我了。
#include<cmath>
#include<queue>
#include<stack>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+;
const int M=N*;
inline int read(){
int X=,w=;char ch=;
while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
while(isdigit(ch))X=(X<<)+(X<<)+(ch^),ch=getchar();
return w?-X:X;
}
struct node{
int u[M],v[M],nxt[M];
int cnt,head[N];
void init(){
cnt=;
memset(head,,sizeof(head));
}
void add(int U,int V){
u[++cnt]=U;v[cnt]=V;nxt[cnt]=head[U];head[U]=cnt;
}
}e,g;
int n,m;
int dfn[N],low[N],to[N],t,l;
ll w[N];
stack<int>q;
void tarjan(int u,int f){
dfn[u]=low[u]=++t;
for(int i=g.head[u];i;i=g.nxt[i]){
int v=g.v[i];
if(!dfn[v]){
q.push(i);
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
int num;l++;
do{
num=q.top();q.pop();
int uu=g.u[num],vv=g.v[num];
if(to[uu]!=l){
to[uu]=l;
e.add(uu,l+n);e.add(l+n,uu);
w[l+n]++;w[uu]=-;
}
if(to[vv]!=l){
to[vv]=l;
e.add(vv,l+n);e.add(l+n,vv);
w[l+n]++;w[vv]=-;
}
}while(num!=i);
}
}else if(low[u]>dfn[v]&&f!=v){
q.push(i);
low[u]=dfn[v];
}
}
}
bool vis[N];
ll ans,size[N],sum;
void dfs1(int u,int f){
vis[u]=;
size[u]=(u<=n);
for(int i=e.head[u];i;i=e.nxt[i]){
int v=e.v[i];
if(v==f)continue;
dfs1(v,u);
size[u]+=size[v];
}
}
void dfs2(int u,int f){
for(int i=e.head[u];i;i=e.nxt[i]){
int v=e.v[i];
if(v==f)continue;
dfs2(v,u);
ans+=w[u]*size[v]*(sum-size[v]);
//以v根树为起点和以v根树补集为终点
//已经暗含了当u合法的时候,以u为终点的路径
}
ans+=w[u]*(sum-size[u])*size[u];
//以u根树补集为起点和以u根树为终点
if(u<=n)ans+=w[u]*(sum-);//以u为起点的路径
}
int main(){
n=read(),m=read();
for(int i=;i<=m;i++){
int u=read(),v=read();
g.add(u,v);g.add(v,u);
}
for(int i=;i<=n;i++)
if(!dfn[i])tarjan(i,);
for(int i=;i<=n;i++){
if(!vis[i]){
dfs1(i,);sum=size[i];dfs2(i,);
}
}
printf("%lld\n",ans);
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++
LOJ2587:[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 先建圆方树. 我们考虑暴力,枚举一个点对,我们枚举的点都是圆点,然后统计中间那个点可以取的位置的数量,加起来就是答案. 那么怎么统计呢,我们对于每个点 ...
随机推荐
- 问题:Visual Studio 2017 无法推送到github:The requested URL returned error: 403
问题: Visual Studio 2017 无法推送到github:The requested URL returned error: 403 原因分析: Visual Studio 2017记录的 ...
- PLSQL-包函数存储过程
包: 包是PLSQL中多个单元的逻辑组合,他将过程组合在一个包内容,以供用户调用,使用后,不需要程序员频繁的修改程序,可以保持程序的逻辑完整性,对包中的过程重新定义或者编译,以便修改部分功能,从而更好 ...
- Oracle 字段拆分替换在合并成一条
看了网上很多Oracle字段拆分的实例,但是都未能完全满足要求,或许是我水平不够未能很好的理解,如果有大神懂得并且愿意告知我的,可以私信我,在这里真诚的感谢! 1. 首先建立表并插入测试数据 drop ...
- 「日常训练」Two Substrings(Codeforces Round 306 Div.2 A)
题意与分析 一道非常坑的水题.分析醒了补. 代码 #include <bits/stdc++.h> #define MP make_pair #define PB emplace_back ...
- tpo-08 C1 submit a document for graduation
第 1 段 1.Listen to a conversation between a student and a registrar. 请听一段学生和老师的对话. 第 2 段 1.Hi, I'd li ...
- python学习笔记02 --------------基础数据类型
python的基本数据类型: 1.基本数据 1.1. 数字类型 1.1.1 整数 int int() #将括号内内容转化为整数类型. 1.1.2 浮点数 float 1.1.3 复 ...
- CodeForces 838B Diverging Directions 兼【20180808模拟测试】t3
描述 给你一个图,一共有 N 个点,2*N-2 条有向边. 边目录按两部分给出 1. 开始的 n-1 条边描述了一颗以 1 号点为根的生成树,即每个点都可以由 1 号点到达. 2. 接下来的 N-1 ...
- Paper Reading - Show, Attend and Tell: Neural Image Caption Generation with Visual Attention ( ICML 2015 )
Link of the Paper: https://arxiv.org/pdf/1502.03044.pdf Main Points: Encoder-Decoder Framework: Enco ...
- Python3 Tkinter-OptionMenu
1.创建 from tkinter import * root=Tk() v=StringVar() v.set('xs') om=OptionMenu(root,v,'Python','PHP',' ...
- Bower 显示‘bower ESUDO Cannot be run with sudo’的错误解决方法
使用 sudo 命令后或者当前用户为 root,执行 bower 相关命令会出现错误: 解决办法: 在命令后面加 --allow-root 例: bower init --allow-root bo ...