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 ...
随机推荐
- UVA 11464 - Even Parity 状态压缩,分析 难度: 2
题目 https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&a ...
- 51nod算法马拉松B
首先将原本字符串hash,注意每一个字母要分开了. 然后并查集判断字符相同,将字符ascll吗乘转化为祖先乘. 然后就可以判断相等的情况. 然后考虑相等的情况. 二分枚举中间点,然后如果左边是不相等并 ...
- 锤子科技 Smartisan M1L 咖啡金 真皮背面 高配版 5.7
http://www.smartisan.com/m1/#/os 快人一步的OS http://www.smartisan.com/shop/#/buyphone?c=coffee&v= ...
- 生产者与消费者问题,C++利用bind基于对象实现与面向对象实现
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 查看json数据更新情况
#! python3 # -*- coding:utf8 -*- #主要为读取excel中接口地址,打开网页爬取url页面中数据,解析json,检查是否符合逻辑(正常) import requests ...
- [leetcode整理]
=======简单 leetcode164 Maximum Gap sort两次 =======有参考 330 Patching Array 98 Validate Binary Search Tre ...
- vsts 管理 持续集成 跟自动化测试
1.代理池: 在服务器上,打开你的TFS Web站点,并转到管理页的代理池页面.如: https://www.cnblogs.com/atwind/p/5486881.html 低版本无法生成高版本. ...
- 2.6 C++通过引用来传递和返回类对象
参考:http://www.weixueyuan.net/view/6338.html 总结: C++语言中,由类声明的对象,和其它类型声明的变量一样,同样可以通过传值.引用和指针的方式作为函数的参数 ...
- Ubuntu16.04 安装Teamviewer
有时需要远程控制ubuntu系统的电脑,Teamviewer在linux下也可以进行安装,大致看了下向日葵在linux下配置好像比较麻烦,而且Teamviewer远程控制的流畅性一直不错,就选择安装T ...
- SharePoint Framework 企业向导(七)
博客地址:http://blog.csdn.net/FoxDave 企业中的SPFx SharePoint是最成功的企业协作平台之一,能够成功的其中一点是它能够进行扩展并作为一个应用集成平台.SP ...