博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU3749 Financial Crisis(点双连通分量+并查集)
阅读量:5921 次
发布时间:2019-06-19

本文共 2360 字,大约阅读时间需要 7 分钟。

题意:

给出一个图和一系列查询,查询是给出两个点,问两点之间有多少条点不重复的路径

要点:

明显是点双连通,如果u,v不连通(并查集处理)输出0;如果u,v处于同一个点双连通分量,输出2(注意这里如果这个分量只有两个点一条边输出1);如果不同,输出1即可。

注意这题有个地方要处理,我们知道割顶可以是好几个点双连通分量的公共点,所以如果直接用白书上的bccno数组来判断割顶处于哪个点双连通分量,它只会显示一个,这里就会出错,所以用一个belong数组把所有能出现的位置都记录下来。

#include
#include
#include
#include
#include
using namespace std;const int maxn = 5050;int pre[maxn], bccno[maxn], dfs_clock, bcc_cnt;//bccno是判断当前点是否已经入块int pa[maxn];typedef pair
Pair;vector
g[maxn], bcc[maxn];//bcc是存放每个块中有的点stack
s;//栈存放当前块中的边vector
belong[maxn];int dfs(int u, int fa){ int lowu = pre[u] = ++dfs_clock; int child = 0; for (int i = 0; i < g[u].size(); i++) { int v = g[u][i]; Pair e = make_pair(u, v); if (!pre[v]) { s.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); if (lowv >= pre[u]) { bcc_cnt++; bcc[bcc_cnt].clear(); while (1)//将当前栈中的边存储 { Pair x = s.top(); s.pop(); if (bccno[x.first] != bcc_cnt) { bcc[bcc_cnt].push_back(x.first); bccno[x.first] = bcc_cnt; belong[x.first].push_back(bcc_cnt);//将割顶放入所有的双连通分量 } if (bccno[x.second] != bcc_cnt) { bcc[bcc_cnt].push_back(x.second); bccno[x.second] = bcc_cnt; belong[x.second].push_back(bcc_cnt); } if (x.first == u&&x.second == v) break; } } } else if (pre[v] < pre[u] && v != fa)//已经访问过就更新low { s.push(e); lowu = min(lowu, pre[v]); } } return lowu;}void find_bcc(int n){ memset(pre, 0, sizeof(pre)); memset(bccno, 0, sizeof(bccno)); while (!s.empty()) s.pop(); dfs_clock = bcc_cnt = 0; for (int i = 1; i <= n; i++) if (!pre[i]) dfs(i, -1);}int find(int i){ return pa[i] == -1 ? i : pa[i]=find(pa[i]);}void init(){ for (int i = 0; i < maxn; i++) { g[i].clear(); bcc[i].clear(); belong[i].clear(); } memset(pa, -1, sizeof(pa));}int main(){ int n, m, q ,kase=1; int x, y,u,v; while (scanf("%d%d%d", &n, &m, &q)) { if (!n && !m && !q) break; init(); for (int i = 1; i <= m; i++) { scanf("%d%d", &x, &y); x++, y++; g[x].push_back(y); g[y].push_back(x); u = find(x); v = find(y); if (u != v) pa[u] = v; } find_bcc(n); printf("Case %d:\n", kase++); while (q--) { int u, v; scanf("%d%d", &u, &v); u++, v++; if (find(u) != find(v)) printf("zero\n"); else { bool flag = false; for (int i = 0; i
2) printf("two or more\n"), flag = true; } } if (!flag) printf("one\n"); } } } return 0;}

转载于:https://www.cnblogs.com/seasonal/p/10343664.html

你可能感兴趣的文章
Primefaces框架开发杂谈!
查看>>
《scp 备份站点 笔记》连带邮件提醒
查看>>
Solaris 10u11 安装python2.7.10
查看>>
常用端口号大全(详细)
查看>>
我的友情链接
查看>>
工欲善其事必先利其器SecureCRT+VMware® Workstation_学习笔记
查看>>
文件和目录权限chmod,更改所有者和所属组chown,umask,隐藏权限lsattr/chattr
查看>>
阿里PB级Kubernetes日志平台建设实践
查看>>
怎么把无线由器限
查看>>
Java实现的冒泡排序
查看>>
APP中的第三方“支付”功能该如何测试
查看>>
HDU 1907
查看>>
数值积分中的辛普森方法及其误差估计
查看>>
Web service (一) 原理和项目开发实战
查看>>
跑带宽度多少合适_跑步机选购跑带要多宽,你的身体早就告诉你了
查看>>
SQL Over
查看>>
shell 批量压缩指定文件夹及子文件夹内图片
查看>>
TextGrocery中文文本分类处理
查看>>
WinForm 之 自定义标题栏的窗体移动
查看>>
可汗学院超经典、超实用概率论总结——商女不知忘国恨,隔江犹看概率论
查看>>