hdu4338 Simple Path
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的更多相关文章
- 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 ...
- 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 ...
- 2019.01.22 zoj3583 Simple Path(并查集+枚举)
传送门 题意简述:给出一张图问不在从sss到ttt所有简单路径上的点数. 思路: 枚举删去每个点然后把整张图用并查集处理一下,同时不跟sss和ttt在同一个连通块的点就是满足要求的点(被删去的不算). ...
- CF 954H Path Counting
H. Path Counting time limit per test 5 seconds memory limit per test 256 megabytes input standard in ...
- linux perf - 性能测试和优化工具
Perf简介 Perf是Linux kernel自带的系统性能优化工具.虽然它的版本还只是0.0.2,Perf已经显现出它强大的实力,足以与目前Linux流行的OProfile相媲美了. Perf 的 ...
- hdu2586 LCA
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...
- Javascript并发模型和事件循环
Javascript并发模型和事件循环 JavaScript的"并发模型"是基于事件循环的,这个并发模型有别于Java的多线程, javascript的并发是单线程的. Javas ...
- HDU2586How far away ?
http://acm.hdu.edu.cn/showproblem.php?pid=2586 How far away ? Time Limit: 2000/1000 MS (Java/Others) ...
- 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 ...
随机推荐
- unity鼠标滚轮控制摄像机视野的缩放和按住鼠标控制摄像机移动
//摄像机前进后退的速率 private float view_value=20f; private float maximum = 100; private float minmum = 30; / ...
- 【转载】linux Jumpserver跳板机堡垒机部署安装使用教程
原文地址:https://idc.wanyunshuju.com/li/554.html
- Flatten Nested List Iterator
Given a nested list of integers, implement an iterator to flatten it. Each element is either an inte ...
- eclipse配置和使用memory Analyse分析内存
1. 安装 在Eclipse help -> Eclipse Marketplace下搜索Memory: 图 1-1 搜索MAT插件 按照步骤安装完成重启即可. 2. 测试代码准备 测试代码 ...
- tomcat的安装及配置
1.首先进tomcat官网下载zip压缩文件:http://tomcat.apache.org/download-90.cgi 2.解压缩到指定文件压(后面配置环境变量会用到) 3.配置环境变量 4. ...
- 简单理解JVM与static{}
参考如下 http://www.cnblogs.com/lao-liang/p/5110710.html http://blog.csdn.net/newjerryj/article/details/ ...
- Flask源码阅读-第三篇(flask\_compat.py)
源码 # -*- coding: utf-8 -*-""" flask._compat ~~~~~~~~~~~~~ Some py2/py3 compatibility ...
- 2017ICPC南宁赛区网络赛 Overlapping Rectangles(重叠矩阵面积和=离散化模板)
There are nnn rectangles on the plane. The problem is to find the area of the union of these rectang ...
- 【Python】多线程-2
1. 进程和线程的区别: (1) 一个进程可以有多个线程,一个进程中的多个线程共享该进程的所有资源,多线程切换比多进程切换快,因为不用上下文切换,Python中并发建议用多进程 (2) 进程是资 ...
- 栈 c实现
栈的数组实现 stack.h #ifndef _STACK_ #define _STACK_ #define SIZE 100 typedef int data_t; typedef struct h ...