Everybody knows that totalfrank has absolutely no sense of direction. Getting lost in the university or nearly supermarket is very common for him. We always worry about whether he can find his way back into our sweet base whenever he goes out alone for his class. In general, if totalfrank get lost again, we need to check his starting point and destination just in order to find out where he could be (you know this task is very common for us).
Unfortunately, poor totalfrank sometimes forgot taking his mobile phone, when this situation happens, we can’t get in touch with him. But it is so lucky that totalfrank can remember places where he had gone before in his trip from his starting point and destination at this trip so that he won’t go to such place again (he can’t remember places which he had gone during his previous trip). As we are all familiar with map, we can find out which place he couldn’t be.
However, totalfrank can always get lost, doing this same boring work makes us sleepy. So we ask totalfrank for all possible starting point and destination for him, and try to find out how many places he wouldn’t be when he chooses any pair of starting point and destination. Here comes the problem, since our university’s map is so complex (there can be many buildings which can be considered as points in our university, some pair of these point has a way while others hasn’t), we need a program to help us work out this problem.

 #pragma comment(linker, "/STACK:102400000,102400000")
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <algorithm>
const int MAXN=1e5+; struct edge{
int u,v,n;
}e1[MAXN*],e2[MAXN*]; int f1[MAXN],f2[MAXN*],es1,es2;
int n,m,q,tu,tv; void addedge1(int u,int v){
e1[es1].u=u,e1[es1].v=v,e1[es1].n=f1[u],f1[u]=es1++;
} void addedge2(int u,int v){
e2[es2].u=u,e2[es2].v=v,e2[es2].n=f2[u],f2[u]=es2++;
} int p[MAXN*]; int find(int x){return x==p[x]?x:p[x]=find(p[x]);} void merge(int x,int y){p[find(x)]=find(y);} int sum[MAXN*],tsum[MAXN*],dis[MAXN];
int lca_f[MAXN*],lca_b[MAXN*],lca_p[MAXN*],rid;
int dminv[MAXN*][],dminid[MAXN*][]; void dp(int u,int f,int dd,int tot){
dis[u]=dd,tsum[u]=tot+sum[u];
lca_f[++rid]=u,lca_b[rid]=dd,lca_p[u]=rid;
for(int i=f2[u];i!=-;i=e2[i].n){
int v=e2[i].v;
if(v==f)continue;
dp(v,u,dd+,tot+sum[u]);
lca_f[++rid]=u,lca_b[rid]=dd;
}
} void makermq(){
rid=;
dp(,-,,);
for(int i=;i<=rid;i++)dminv[i][]=lca_b[i],dminid[i][]=i;
int maxj=(int)(log(rid+1.0)/log(2.0));
for(int j=;j<=maxj;j++){
int maxi=rid+-(<<j);
for(int i=;i<=maxi;i++){
if(dminv[i][j-]<dminv[i+(<<(j-))][j-]){
dminv[i][j]=dminv[i][j-];
dminid[i][j]=dminid[i][j-];
}else{
dminv[i][j]=dminv[i+(<<(j-))][j-];
dminid[i][j]=dminid[i+(<<(j-))][j-];
}
}
}
} int lca(int x,int y){
if(lca_p[x]>lca_p[y])std::swap(x,y);
x=lca_p[x],y=lca_p[y];
int k=(int)(log(y-x+1.0)/log(2.0));
int xx=dminv[x][k]<dminv[y+-(<<k)][k]?dminid[x][k]:dminid[y+-(<<k)][k];
return lca_f[xx];
} int dfn[MAXN],low[MAXN],cid[MAXN],stk[MAXN],col[MAXN],top,ind,cls,tmp;
int cal[MAXN*]; void dfs_cutpnt(int u,int f,int root){
dfn[u]=low[u]=++ind;
int cnt=;
int flag=;
for(int i=f1[u];i!=-;i=e1[i].n){
int v=e1[i].v;
if(v==f&&!flag){flag=;continue;}
if(!dfn[v]){
cnt++;
dfs_cutpnt(v,u,root);
if(low[v]<low[u])low[u]=low[v];
if(u==root&&cnt>&&cid[u]==)cid[u]=++cls,sum[cls]=;
else if(u!=root&&low[v]>=dfn[u]&&cid[u]==)cid[u]=++cls,sum[cls]=;
}else if(dfn[v]<low[u])low[u]=dfn[v];
}
} void dfs_tarjan(int u,int f){
low[u]=dfn[u]=++ind;
stk[++top]=u;
int flag=;
for(int i=f1[u];i!=-;i=e1[i].n){
int v=e1[i].v;
if(v==f&&!flag){flag=;continue;}
if(!dfn[v]){
dfs_tarjan(v,u);
if(low[v]<low[u])low[u]=low[v];
if(low[v]>=dfn[u]){
sum[++cls]=,col[u]=cls;
do{
tmp=stk[top--],col[tmp]=cls,++sum[cls];
if(cid[tmp]){addedge2(cid[tmp],cls);addedge2(cls,cid[tmp]);merge(cid[tmp],cls);}
}while(tmp!=v);
if(cid[u]){addedge2(cid[u],cls);addedge2(cls,cid[u]);merge(cid[u],cls);}
}
}else if(dfn[v]<low[u])low[u]=dfn[v];
}
} int size; void makegraph(){
//找割点
memset(dfn,,sizeof dfn);
memset(low,,sizeof low);
memset(cid,,sizeof cid);
cls=ind=;
//找双联通分量并建图
for(int i=;i<n;i++)dfs_cutpnt(i,-,i);
memset(dfn,,sizeof dfn);
memset(low,,sizeof low);
memset(col,,sizeof col);
top=ind=;
for(int i=;i<n;i++)dfs_tarjan(i,-);
//将森林补成树,便于dp以及查询
memset(cal,,sizeof cal);
for(int i=;i<=cls;i++){
if(cal[find(i)]==){
cal[find(i)]=;
addedge2(,i);
}
}
} int main(){
//freopen("test.in","r",stdin);
int cas=;
while(scanf("%d%d",&n,&m)!=EOF){
memset(f1,-,sizeof f1);
memset(f2,-,sizeof f2);
for(int i=;i<=*n;i++)p[i]=i;
es1=es2=; for(int i=;i<m;i++){
scanf("%d%d",&tu,&tv);
addedge1(tu,tv);
addedge1(tv,tu);
} //转化成双联通与割点相邻的图
makegraph();
//lca转化成rmq
makermq(); printf("Case #%d:\n",cas++);
scanf("%d",&q);
while(q--){
scanf("%d%d",&tu,&tv);
//起点和终点重合
if(tu==tv)printf("%d\n",n-);
else{
//如果是割点的话就一定要用割点对应的点,因为割点会被染成不同的颜色!
tu=cid[tu]?cid[tu]:col[tu];
tv=cid[tv]?cid[tv]:col[tv];
//孤立点或者不在同一个联通块中
if(tu==||tv==||find(tu)!=find(tv)){
printf("%d\n",n);
}else{
int fa=lca(tu,tv);
int ans=tsum[tu]+tsum[tv]-*tsum[fa]+sum[fa];
ans-=(dis[tu]+dis[tv]-*dis[fa]);
printf("%d\n",n-ans);
}
}
}
printf("\n");
}
return ;
}

hdu4338 Simple Path的更多相关文章

  1. Simple Path Data Resources that I Add to Every WPF and Silverlight Project

    Here’s a little time saver. I sort of have a routine that I go through when I create a new WPF proje ...

  2. Each path can be reduced to a simple path

    Recently, I made a small conclusion, but I found it is found and well-founded in some textbook. So I ...

  3. 2019.01.22 zoj3583 Simple Path(并查集+枚举)

    传送门 题意简述:给出一张图问不在从sss到ttt所有简单路径上的点数. 思路: 枚举删去每个点然后把整张图用并查集处理一下,同时不跟sss和ttt在同一个连通块的点就是满足要求的点(被删去的不算). ...

  4. CF 954H Path Counting

    H. Path Counting time limit per test 5 seconds memory limit per test 256 megabytes input standard in ...

  5. linux perf - 性能测试和优化工具

    Perf简介 Perf是Linux kernel自带的系统性能优化工具.虽然它的版本还只是0.0.2,Perf已经显现出它强大的实力,足以与目前Linux流行的OProfile相媲美了. Perf 的 ...

  6. hdu2586 LCA

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  7. Javascript并发模型和事件循环

    Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...

  8. HDU2586How far away ?

    http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Others) ...

  9. Codeforces Round #381 (Div. 2)D. Alyona and a tree(树+二分+dfs)

    D. Alyona and a tree Problem Description: Alyona has a tree with n vertices. The root of the tree is ...

随机推荐

  1. windows 网络操作

    ver 命令 显示当前机器上的操作系统版本信息 ipconfig/release 释放IP地址 ipconfig/renew 重新获取IP地址 cmd下使用ssh 如果想在cmd中输入 ssh xx@ ...

  2. Win10系列:VC++绘制位图图片

    在使用Direct2D绘制图片的过程中,通过IWICImagingFactory工厂接口来得到绘制图片所需要的资源.本小节将介绍如何通过IWICImagingFactory工厂接口得到这些资源,并使用 ...

  3. win7 php nginx 启动命令

    1 php 启动命令 @echo off e: cd E:/php-/ echo "php is starting on port 9007, php_version is 7.0.6&qu ...

  4. Uva LA 3177 - Beijing Guards 贪心,特例分析,判断器+二分,记录区间内状态数目来染色 难度: 3

    题目 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  5. es6新增的math函数有哪些

    Math.trunc():用于去除一个数的小数部分,返回整数部分. Math.sign():用来判断一个数到底是正数.负数.还是零. Math.cbrt():用于计算一个数的立方根. Math.hyp ...

  6. 真实分享记录我学习Linux系统遇到的问题

    对于linux,又爱又恨,也有自己的一些看法,毕竟已经接触了快两年了.但是,说出来都是伤,为什么呢?如果您想知道请让我给您慢慢道来. 最开始接触linux是在高考完后,由于我家的台式电脑太卡,于是我就 ...

  7. markdown语法模板

    (GitHub-Flavored) Markdown Editor Basic useful feature list: Ctrl+S / Cmd+S to save the file Ctrl+Sh ...

  8. TiDB 深度实践之旅--真实“踩坑”经历

    美团点评 TiDB 深度实践之旅(9000 字长文 / 真实“踩坑”经历) 4   PingCAP · 154 天前 · 3956 次点击 这是一个创建于 154 天前的主题,其中的信息可能已经有所发 ...

  9. [ZJOI2008]泡泡堂BNB

    这个题...是一道神奇的贪心题... 根据田忌赛马的原理... 先假使两队都符合田忌和齐王的配置... 我们可以发现如果我们用当前最弱的...去和对方当前最强的打... 然后一直按照这个方案...当我 ...

  10. shiro学习笔记(四) ini配置以及加解密

    INI配置 从之前的Shiro架构图可以看出,Shiro是从根对象SecurityManager进行身份验证和授权的:也就是所有操作都是自它开始的,这个对象是线程安全且真个应用只需要一个即可,因此Sh ...