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. 1-3Controller之Response

    控制器中的方法: public function response1(){ /*响应的常见类型: * 1.字符串 * 2.视图 * 3.json * 4.重定向 * */ //响应JSON /*$da ...

  2. Entrust - Laravel 用户权限系统解决方案

    Zizaco/Entrust 是 Laravel 下 用户权限系统 的解决方案, 配合 用户身份认证 扩展包 Zizaco/confide 使用, 可以快速搭建出一套具备高扩展性的用户系统. Conf ...

  3. Java第5次

    1. 请运行以下示例代码StringPool.java,查看其输出结果.如何解释这样的输出结果?从中你能总结出什么? 显示结果: truetruefalse 总结:在Java中,内容相同的字串常量(“ ...

  4. 一: Docker的概念

    附件:https://files.cnblogs.com/files/chaos-li/docker-k8s-devops-master-9287a2ca56433ca076078b564de9488 ...

  5. Cracking The Coding Interview 4.4

    //Given a binary search tree, design an algorithm which creates a linked list of all the nodes at ea ...

  6. error MSB8008: 指定的平台工具集(V120)未安装或无效。

    打开项目属性->配置属性->右面,平台工作集,选为v10 如下图

  7. SQL-36 创建一个actor_name表,将actor表中的所有first_name以及last_name导入改表。

    题目描述               对于如下表actor,其对应的数据为: actor_id first_name last_name last_update 1 PENELOPE GUINESS ...

  8. C语言获取系统时间的几种方式

    C语言获取系统时间的几种方式 2009-07-22 11:18:50|  分类: 编程学习 |字号 订阅     C语言中如何获取时间?精度如何? 1 使用time_t time( time_t * ...

  9. L251

    Beer before wine, or wine before beer; whatever the order, you’ll feel queer. That, at least, is the ...

  10. python生产者消费者模型优点

    生产者消费者模型:解耦,通过队列降低耦合,支持并发,生产者和消费者是两个独立的并发体,他们之间使用缓存区作为桥梁连接,生产者指望里丢数据,就可以生产下一个数据了,消费者从中拿数据,这样就不会阻塞,影响 ...