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 先建圆方树. 我们考虑暴力,枚举一个点对,我们枚举的点都是圆点,然后统计中间那个点可以取的位置的数量,加起来就是答案. 那么怎么统计呢,我们对于每个点 ...
随机推荐
- Weka java.lang.reflect.InvocationTargetException
在用Weka导入数据的时候报 java.lang.reflect.InvocationTargetException 错误,Weka运行包没有给出详细的错误信息,无法查到. 直接调试Weka源码,发现 ...
- 「国庆训练」Kingdom of Obsession(HDU-5943)
题意 给定\(s,n\),把\(s+1,s+2,...,s+n\)这\(n\)个数填到\(1,2,...,n\)里,要求\(x\)只能填到\(x\)的因子的位置(即题目中\(x\%y=0\)那么x才能 ...
- poj3984迷宫问题(dfs+stack)
迷宫问题 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 35426 Accepted: 20088 Descriptio ...
- JavaScript写的一个带AI的井字棋
最近有一门课结束了,需要做一个井字棋的游戏,我用JavaScript写了一个.首先界面应该问题不大,用html稍微写一下就可以.主要是人机对弈时的ai算法,如何使电脑方聪明起来,是值得思考一下的.开始 ...
- 【转】: 探索Lua5.2内部实现:虚拟机指令(2) MOVE & LOAD
name args desc OP_MOVE A B R(A) := R(B) OP_MOVE用来将寄存器B中的值拷贝到寄存器A中.由于Lua是register based vm,大部分的指令都是直接 ...
- 实现Bidirectional LSTM Classifier----深度学习RNN
双向循环神经网络(Bidirectional Recurrent Neural Networks,Bi-RNN),Schuster.Paliwal,1997年首次提出,和LSTM同年.Bi-RNN,增 ...
- Error: Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster
自己搭建了一套伪分布的大数据环境,运行Hadoop包中自带的示例时,出现如下错误: 错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMas ...
- 如何做好FAE工作及FAE职位发展
此文较长,是作者对于半导体FAE职业的一些总结,码字不容易,耐心的阅读,欢迎点赞. 曾经认识一位做电源研发的工程师,转行在一家代理商做FAE,做了一年半以后,就提出了离职请求,他老板问他是什么原因,他 ...
- WPF+数据库+三层
1.计算类 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...
- CodeForces - 792C Divide by Three (DP做法)
C. Divide by Three time limit per test: 1 second memory limit per test: 256 megabytes input: standar ...