【题目大意】

给你一个无向图。问,从点u到点v,若是只走简单路径,有多少个点不能到达?

【思路】

这题肯定是要双连通缩点的,以前老是觉得点双连通不会用来缩点,因为割点可以属于多个连通集合,现在立马打脸了 o(╯□╰)o

最开始用,边-双连通思考,然后发现下面这种图就....

如果我们询问(6,7)和(6,4),显然两次点6所属集团的意义不同;除此之外,比方(1,2,3)这个集团,直接合并也是不合理的,询问(1,3)和(3,7),点3的意义也是不同的

问题的关键,其实关键就是割点。如果对点双连通比较熟悉的话,应该能想到:除了孤点,任何点都会至少属于一个连通集合,而只有割点能属于2个及以上的集合。连通集合一定是通过割点相连的。

所以,我们可以考虑把原图改成通过割点相连的形式。上面那个图就可以改成

显然,每条边的一段都是连通集合,而另一段是割点。

仔细分析割点到割点、非割点到非割点、割点到非割点三种情况,你会发现,点u到点v,能走的点就是修改后的图(这个图不会有环)对应的简单路径上的所有的点。比方(2,5)能经过的点就为 {2}∪{1,2,3}∪{3}∪{3,5}∪{5} == {1,2,3,5} ,(2,6)的为 {2}∪{1,2,3}∪{3}∪{3,5}∪{5}∪{4,5,6} == {1,2,3,4,5,6}。

因为路径上的点是有重复的,我们仍需要思考一下。实际上,点的数目,等于每个点的点的数目减去路径上的边数。

而具体怎么去求无环图上一个简单路径上的点数和以及边数和。这里可以采用多种方法,我这里用的lca维护一下。

P.S. 数据好像不严,询问中有点的编号>=n的情况,我这种情况是直接输出n

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef __int64 LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const LL INF = 1LL<<55;
const double INFF = 1e100;
const double eps = 1e-8;
const LL mod = 10000000007LL;
const int NN = 100010;
const int MM = 400010;
/* ****************** */int dfn[NN], low[NN], tsp;
int sta[MM], sta_top;
int id[NN], num[NN*2], id_cnt;
int color[NN];
vector<int>bccno[NN];
struct G
{int u, v, next;
}E[MM], E1[MM];
int p1[NN], T1;
int p[NN*2], T;int long2[NN*2*2];
int deep[NN*2], pos[NN*2], dian[NN*2];
int oula[NN*2*2];
int rmq[NN*2*2][20];void init_long2(int n)
{int i;long2[1]=0;for(i=2;i<=n;i++){long2[i]=long2[i-1]+(i==(i&(-i)));}
}void add(int u,int v,G *E,int *p,int &T)
{E[T].u = u;E[T].v = v;E[T].next = p[u];p[u] = T++;
}void bcc(int u,int fa,int col)
{int i, ii, v;dfn[u] = low[u] = ++tsp;color[u] = col;for(i = p1[u]; i + 1; i = E1[i].next){v = E1[i].v;if(dfn[v]==0){sta[++sta_top] = i;bcc(v, u, col);low[u] = min(low[u], low[v]);if(low[v] >= dfn[u]){num[++id_cnt] = 0;for(;;){ii = sta[sta_top--];if(id[ E1[ii].u ] != id_cnt){bccno[ E1[ii].u ].PB(id_cnt);num[id_cnt] ++;id[ E1[ii].u ] = id_cnt;}if(id[ E1[ii].v ] != id_cnt){bccno[ E1[ii].v ].PB(id_cnt);num[id_cnt] ++;id[ E1[ii].v ] = id_cnt;}if(E1[ii].u == u && E1[ii].v == v)break;}}}else if(dfn[v]<dfn[u] && v != fa){sta[++sta_top] = i;low[u] = min(low[u], dfn[v]);}}
}
//生成欧拉序列,计算每个节点深度,每个点首次出现的位置
//其第一个父亲,没有用-1表示
void dfs(int u,int fa,int cen)
{oula[++tsp]=u;deep[u]=cen;pos[u]=tsp;int i,v;for(i=p[u];i+1;i=E[i].next){v=E[i].v;if(v!=fa){dian[v] = dian[u] + num[v];dfs(v,u,cen+1);oula[++tsp]=u;}}
}
//用于lca的rmq
void init_rmq(int n)
{int i,j,en,len;int t1,t2;for(i=1;i<=n;i++)rmq[i][0]=i;for(j=1;j<=long2[n];j++){en=n+1-(1<<j);len=1<<(j-1);for(i=1;i<=en;i++){t1=oula[ rmq[i][j-1] ];t2=oula[ rmq[i+len][j-1] ];if(deep[t1]<deep[t2])rmq[i][j]=rmq[i][j-1];elsermq[i][j]=rmq[i+len][j-1];}}
}
int ask_lca(int u,int v)
{int st=pos[u];int en=pos[v];if(st>en)swap(st,en);int k=long2[en-st+1];int id1=oula[ rmq[st][k] ];int id2=oula[ rmq[en+1-(1<<k)][k] ];if(deep[id1]<deep[id2])return id1;return id2;
}void solve(int n,int sum_n)
{int m,i,u,v,ans;tsp=0;for(i=1;i<=n;i++)pos[i] = -1;for(i=1;i<=n;i++){if(pos[i]==-1){dian[i] = num[i];dfs(i,-1,0);}}init_rmq(tsp);scanf("%d",&m);while(m--){scanf("%d%d",&u,&v);if(u>=sum_n || v>=sum_n){printf("%d\n",sum_n);//   while(1);continue;}u++, v++;if(u==v)printf("%d\n", sum_n-1);else if(color[u]!=color[v])printf("%d\n", sum_n);else{u = id[u];v = id[v];i = ask_lca(u, v);ans = dian[u] + dian[v] - dian[i]*2 + num[i];ans -= (deep[u]+deep[v]-deep[i]*2);ans = sum_n - ans;printf("%d\n",ans);}}puts("");
}int main()
{init_long2(100000*4);int n, m, i, j, u, v,  si;int ee = 0;while(scanf("%d%d", &n, &m) != EOF){memset(p1, -1, sizeof(p1));T1 = 0;for(i = 0; i < m; i ++){scanf("%d%d", &u, &v);u ++, v ++;add(u, v, E1, p1, T1);add(v, u, E1, p1, T1);}memset(dfn, 0, sizeof(dfn));memset(id, -1, sizeof(id));tsp = 0;id_cnt = 0;sta_top = 0;for(i = 1; i <= n; i ++){if(dfn[i]==0){bcc(i, -1, i);}}memset(p, -1, sizeof(p));T = 0;for(i = 1; i <= n; i ++){si = bccno[i].size();if(si > 1){u = ++id_cnt;id[i] = u;num[u] = 1;for(j = 0; j < si; j ++){v = bccno[i][j];add(u, v, E, p, T);add(v, u, E, p, T);}}bccno[i].clear();}printf("Case #%d:\n",++ee);solve(id_cnt, n);}return 0;
}

HDU 4338 Simple Path 点双连通+lca相关推荐

  1. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  2. 图论之tarjan真乃神人也,强连通分量,割点,桥,双连通他都会

    先来%一下Robert Tarjan前辈 %%%%%%%%%%%%%%%%%% 然后是热情感谢下列并不止这些大佬的博客: 图连通性(一):Tarjan算法求解有向图强连通分量 图连通性(二):Tarj ...

  3. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  4. HDU 3394 Railway(点双连通分量)

    题目大意 一个公园中有 n 个景点,景点之间通过无向的道路来连接,如果至少两个环公用一条路,路上的游客就会发生冲突:如果一条路不属于任何的环,这条路就没必要修 问,有多少路不必修,有多少路会发生冲突 ...

  5. POJ 3177 Redundant Paths (边双连通+缩点)

    <题目链接> <转载于 >>>  > 题目大意: 有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新 ...

  6. 模板:割点、桥与双连通

    文章目录 割点 代码 桥 点双连通分量 代码 边双连通分量 代码 割点 和强连通分量十分相似 分为树枝边.前向边和后向边 注意! if(x!=r&&low[to]>=dfn[x] ...

  7. poj 3177 Redundant Paths(tarjan边双连通)

    题目链接:http://poj.org/problem?id=3177 题意:求最少加几条边使得没对点都有至少两条路互通. 题解:边双连通顾名思义,可以先求一下连通块显然连通块里的点都是双连通的,然后 ...

  8. Tarjan算法 —— 强连通双连通缩点 模板

    TP 强连通缩点模板 双连通缩点模板 边双连通 点双连通 有向图 我们知道在一张 有向无环 图(也叫 DAG)中,肯定存在拓扑序.拓扑序的特殊顺序性质,能够允许我们在 O(n+m)O(n + m)O( ...

  9. 【FZU】Problem 2181 快来买肉松饼 点双连通

    传送门:[FZU]Problem 2181 快来买肉松饼 题目分析:无向图找奇圈的问题.首先我们做tarjan求出点双连通块,每一个块中用黑白染色法得到最长的奇圈,然后这个奇圈中不参加游戏的小孩就是这 ...

最新文章

  1. 糊涂的教授【拓扑排序】
  2. 计算机组成原理题库带答案详解,计算机组成原理试试题库(含答案解析) -.doc
  3. 【Java面试题】49 垃圾回收的优点和原理。并考虑2种回收机制。
  4. 你必须掌握的20个python代码,短小精悍,用处无穷
  5. Android NFC开发-实践篇
  6. 计算机信息管理专业技能评价,计算机信息管理专业个人技能范文
  7. The GenerateResource task failed unexpectedly. a generic error occured in GDI+
  8. PBC密码学库使用指南
  9. 在线扒站工具, 扒站网站工具(简单、快捷、免费)
  10. 异速联未获取服务器信息,异速联客户端连接服务器的方法
  11. OA软件详细功能模块列表
  12. matlab求任意输入响应曲线,3.6 用Matlab进行动态响应分析
  13. 2019年厦门大学计算机系夏令营经历
  14. 蒙泰RIP快捷键大全
  15. TDSCDMA手机N270 新邮通开包尝鲜!
  16. CakePHP系列(一)----CakePHP3.4一览
  17. 二分法查找 (长沙戴维营教育)
  18. 软件架构师应该知道的 97 件事笔记
  19. 【自动驾驶传感器——摄像头】
  20. 大智慧服务器 列表不显示,为什么大智慧level 2均线显示不正常!!

热门文章

  1. 聚划算安卓客户端1期教训总结
  2. 计算机控制原理实验报告,计算机组成原理实验报告范文
  3. 电商违禁词查询工具在线检查
  4. 天心sunlike erp 生产需求分析 按生产订单号生成单号
  5. MOSS和LCS的集成
  6. 会议OA项目之会议排座功能会议送审的实现
  7. signature=152c7128f5309ebd73e4a1d7e8516c1b,交流传动内燃机逻辑控制单元的开发设计
  8. 《可以量化的经济学》可以购买了,…
  9. Coursera机器学习(Andrew Ng)笔记:无监督学习与维度约减
  10. 成都市等2009年《四川省建设工程清单计价定额》人工费调整的批复〔2019〕5号