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. linux用户管理 查看用户信息

    LINUX系统中用户登录查看命令 W命令 [root@ssgao1987 ~]# w 04:57:01 up 11:50,  2 users,  load average: 0.00, 0.00, 0 ...

  2. 尚学堂java 答案解析 第四章

    本答案为本人个人编辑,仅供参考,如果读者发现,请私信本人或在下方评论,提醒本人修改 一.选择题 1.BD 解析:B:类必须有构造方法,若程序未写,这系统自动调用系统构造方法. D:super()会调用 ...

  3. 服务消费和负载(Feign)

    Spring Cloud Feign Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口 ...

  4. :适配器模式:Adapter

    #ifndef __ADAPTER_H__ #define __ADAPTER_H__ #include <iostream> using namespace std; class Duc ...

  5. FPGA的GTP(aurora 协议)高速串行接口数据收发(转)

    reference:https://blog.csdn.net/qq_40261818/article/details/83039829 PG046-Aurora 8B/10B  Logicore I ...

  6. 二、求水仙花数,打印出100-999之间所有的"水仙花数"

    所谓"水仙花数"是指一个三位数,其各位数字立方和等于该数本身. 例如:153是一个"水仙花数",因为153=1的三次方+5的三次方+3的三次方 public c ...

  7. MyEclipse使用教程:使用REST Web Services管理JPA实体

    MyEclipse 在线订购专享特惠!火爆开抢>> MyEclipse最新版下载 使用REST Web Services来管理JPA实体.在逆向工程数据库表后生成REST Web服务,下面 ...

  8. mybatis学习(一)----入门

    一.Mybatis介绍 MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名 ...

  9. countdownlatch 和 CyclicBarrier 和 Semaphore

    cdl用的是aqs,共享的是aqs那个volatile的state,阻塞线程列表用的也是aqs的 cb用的是reentrantlock+condition,当然rel用的也是aqs不过不同的是用的是互 ...

  10. C点滴成海------Dev C++怎么修改成简体中文

    第一步:选择菜单中的Tools 第二步:选择Tools中的“Envirnoment Options”,即第二个选项 第三步:选择中文并保存 将"1"的语言改成中文就行了