题目描述

输入

输出

样例输入

4 4 2

1 2

2 3

3 2

3 4

1 2

1 4

样例输出

14

数据范围

样例解释

upd:保证原图连通。

“不相交路径”的定义为不存在相同的边。可以存在相同的点。重边视为不同的边。

对于样例:

原图有2个安全点对为(2,3),(3,2)

询问1答案为4,新增的安全点对为(1,2),(1,3),(2,1)(3,1)

询问2答案为10,新增的安全点对为(1,2),(1,3),(1,4),(2,1)(2,4),(3,1),(3,4),(4,1),(4,2),(4,3)

因此输出14

解法

利用边双连通分量缩点,再利用lca统计答案。

代码

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<algorithm>
#define ll long long
#define ln(x,y) (ll)(log(x)/log(y))
#define sqr(x) ((x)*(x))
using namespace std;
const char* fin="aP3.in";
const char* fout="aP3.out";
const ll inf=0x7fffffff;
const ll maxn=400007,maxm=maxn*4,maxk=22;
ll n,m,t,i,j,k,l,tot,limit,tmp,cnt;
ll fi[maxn],ne[maxm],la[maxm],de[maxn];
ll fa[maxn][maxk],sum[maxn][maxk],qsum[maxn][maxk];
ll dfn[maxn],low[maxn],num,stack[maxn],blg[maxn];
ll az[maxn];
ll ans;
bool bz[maxn],cz[maxn],dz[maxn];
ll read(){
ll x=0;
char ch=getchar();
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
void add_line(ll a,ll b){
tot++;
ne[tot]=fi[a];
la[tot]=b;
fi[a]=tot;
}
void dfs(ll v,ll from){
ll i,j,k;
cz[v]=true;
fa[v][0]=from;
qsum[v][0]=sqr(sum[v][0]);
de[v]=de[from]+1;
for (i=1,j=ln(de[v],2);i<=j;i++){
k=fa[v][i-1];
fa[v][i]=fa[k][i-1];
sum[v][i]=sum[v][i-1]+sum[k][i-1];
qsum[v][i]=qsum[v][i-1]+qsum[k][i-1];
}
for (k=fi[v];k;k=ne[k]){
if (!cz[az[blg[la[k]]]]){
dfs(az[blg[la[k]]],v);
}
}
}
void up(ll &a,ll i,ll &j,ll &k){
j+=sum[a][i];
k+=qsum[a][i];
a=fa[a][i];
}
ll lca(ll a,ll b){
ll i,j=0,k=0;
if (de[a]<de[b]) swap(a,b);
for (i=ln(de[a]-de[b],2);i>=0;i--) if (de[fa[a][i]]>de[b]) up(a,i,j,k);
if (de[a]!=de[b]) up(a,0,j,k);
for (i=ln(de[a],2);i>=0;i--) if (fa[a][i]!=fa[b][i]) up(a,i,j,k),up(b,i,j,k);
if (a!=b) up(a,0,j,k),up(b,0,j,k);
j+=sum[a][0];
k+=qsum[a][0];
return sqr(j)-k;
}
void tarjan(ll v,ll from){
ll i,j,k;
dfn[v]=low[v]=++num;
bz[j=stack[++stack[0]]=v]=true;
for (k=fi[v];k;k=ne[k])
if (!dz[(k+1)/2]){
dz[(k+1)/2]=true;
if (!dfn[la[k]]){
tarjan(la[k],v);
low[v]=min(low[la[k]],low[v]);
}else if (bz[la[k]]) low[v]=min(low[v],dfn[la[k]]);
}
if (low[v]==dfn[v]){
while (stack[stack[0]]!=j){
blg[stack[stack[0]]]=v;
bz[stack[stack[0]--]]=false;
}
blg[stack[stack[0]]]=v;
bz[stack[stack[0]--]]=false;
}
}
int main(){
cnt=n=read();m=read();t=read();
for (i=1;i<=m;i++){
j=read();k=read();
add_line(j,k);
add_line(k,j);
}
tarjan(1,0);
for (i=1;i<=n;i++){
if (!az[blg[i]]) az[blg[i]]=++cnt;
sum[az[blg[i]]][0]++;
for (k=fi[i];k;k=ne[k]) add_line(az[blg[i]],la[k]);
}
dfs(n+1,0);
for (i=1;i<=t;i++){
j=read();
k=read();
ans+=lca(az[blg[j]],az[blg[k]]);
}
printf("%lld\n",ans);
return 0;
}

启发

边双连通分量在某种程度上等同于强连通分量。

【JZOJ4784】【NOIP2016提高A组模拟9.15】Map的更多相关文章

  1. NOIP2016提高A组模拟10.15总结

    第一题,就是将原有的式子一步步简化,不过有点麻烦,搞了很久. 第二题,枚举上下边界,维护一个单调队列,二分. 比赛上没有想到,只打了个暴力,坑了80分. 第三题,贪心,最后的十多分钟才想到,没有打出来 ...

  2. 【NOIP2016提高A组模拟10.15】打膈膜

    题目 分析 贪心, 先将怪物按生命值从小到大排序(显然按这个顺序打是最优的) 枚举可以发对少次群体攻击, 首先将所有的群体攻击发出去, 然后一个一个怪物打,当当前怪物生命值大于2,如果还有魔法值就放重 ...

  3. 【NOIP2016提高A组模拟10.15】最大化

    题目 分析 枚举两个纵坐标i.j,接着表示枚举区域的上下边界, 设对于每个横坐标区域的前缀和和为\(s_l\),枚举k, 显然当\(s_k>s_l\)时,以(i,k)为左上角,(j,k)为右下角 ...

  4. 【NOIP2016提高A组模拟10.15】算循环

    题目 分析 一步步删掉循环, 首先,原式是\[\sum_{i=1}^n\sum_{j=1}^m\sum_{k=i}^n\sum_{l=j}^m\sum_{p=i}^k\sum_{q=j}^l1\] 删 ...

  5. 【NOIP2016提高A组模拟9.15】Map

    题目 分析 发现,当原图是一棵树的时候,那么新建一条边后,就会变成环套树, 而环内的所有点对都是安全点对,如果环中有k个点,答案就是\(k(k-1)\) 联想到,当把原图做一遍tarjan缩点,每个环 ...

  6. 【NOIP2016提高A组模拟9.15】Osu

    题目 分析 考虑二分答案, 二分小数显然是不可取的,那么我们将所有可能的答案求出来,记录在一个数组上,排个序(C++调用函数很容易超时,手打快排,时间复杂度约为\(O(>8*10^7)\),但相 ...

  7. 【NOIP2016提高A组模拟9.15】Math

    题目 分析 因为\((-1)^2=1\), 所以我们只用看\(\sum_{j=1}^md(i·j)\)的值模2的值就可以了. 易证,一个数x,只有当x是完全平方数时,d(x)才为奇数,否则为偶数. 那 ...

  8. 【NOIP2016提高A组模拟8.15】Garden

    题目 分析 其实原题就是[cqoi2012][bzoj2669]局部极小值. 有一个n行m列的整数矩阵,其中1到nm之间的每个整数恰好出现一次.如果一个格子比所有相邻格子(相邻是指有公共边或公共顶点) ...

  9. 【NOIP2016提高A组模拟8.15】Throw

    题目 分析 首先对于一个状态(a,b,c),假定a<=b<=c: 现在考虑一下这个状态,的转移方案: \[1,中间向两边跳(a,b,c)-->(a*2-b,a,c).(a,b,c)- ...

随机推荐

  1. vue.js_11_路由的2中参数传递和路由的嵌套

    1.以?的形式传递参数   <router-link to="/login?id=10&name=zs">登录</router-link> 发送参数 ...

  2. PHP--时间搜索插件封装

    /** * 时间搜索插件封装 * anthor qinpeizhou * @param $timeset 时间格式 * @param $time sql语句中所需要搜索的time字段名称 * @par ...

  3. linux学习(二)-----Linux 的目录结构、远程登录、vi和vim

    linux目录结构 基本介绍 linux 的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录“/”,然后在此 目录下再创建其他的目录. 目录结构具体介绍 Linux 目录总结 1.lin ...

  4. 【agc013d】AtCoder Grand Contest 013 D - Piling Up

    题意 盒子里有n块砖,每块的颜色可能为蓝色或红色. 执行m次三步操作: 1.从盒子里随便拿走一块砖 2.放入一块蓝砖和红砖到盒子里 3.从盒子里随便拿走一块砖 给定n,m 问拿出来的砖,可能有多少种不 ...

  5. 【DM642学习笔记三】flash的烧写

    ICETEK-DM642-PCI板上的29L008B芯片提供了8M位的Flash空间(访问地址空间是CE1,90000000h~90080000h).主要用于自启动功能和存储FPGA的配置数据. 一. ...

  6. IO流18 --- RandomAccessFile实现数据的读写操作 --- 技术搬运工(尚硅谷)

    RandomAccessFile实例化时,需要设置读写模式 示例:复制文件 @Test public void test16() throws IOException { RandomAccessFi ...

  7. Python - 集合与元素之数据类型和变量总结

    变量 变量的作用:保存状态(程序的运行本质是一系列的变化,变量的目的就是用来保存状态,变量值的变化就构成了程序运行的不同结果.) 例如:cs枪战中,一个人的生命可以表示为life = True 表示存 ...

  8. Object上的静态方法

    内置提供了一个对象为 Object ,也被称之为是构造函数,用来创建对象用的.在 javascript 函数也是对象,是一种可被执行的对象,所以称Object为对象也是可以的.挂在函数上的方法,称之为 ...

  9. hbase表内存的分布

  10. Vuejs实战项目四:权限校验

    路由跳转参考文档:https://router.vuejs.org/zh/guide/advanced/navigation-guards.html 在/src下创建permission.js进行权限 ...