<题目连接>

题目大意:

  给你一个(保证输入无重边,无自环)无向图,然后有下面Q条询问,每条询问为:问你u点与v点之间有几条(除了首尾两点外,其他点不重复)的路径.如果有0条或1条输出0或1,如果有2条以上,输出”two or more”.

解题分析:

  我们可以用并查集判断两点之间是否有路径相连通,如果两点不连通,则直接输出0即可。至于判断两点之间有几条不重复的路径相连,则是通过这两点是否属于同一点双连通分量来判断。不过需要注意的是,我们应该排除只有两个点的点双连通分量这一特殊情况。所以综上,只要待查询的两点属于点数大于2的点双连通分量,则直接输出"two or more"(在已经判断这两点连通的情况下),否则输出"one"。

#include <bits/stdc++.h>
using namespace std; #define pb push_back
#define rp(i, s, t) for (int i = s; i < t; i++)
#define clr(a, b) memset(a, b, sizeof(a))
const int N = 5e3 + ;
int n, m, q;
int tot, bcc;
int dfn[N], low[N], col[N], fa[N]; //col[i]表示的是这个点当前所属的点双连通分量的编号
vector<int> G[N], BCC[N], bl[N]; //bl[i]表示第i个节点属于的所有点双连通分量编号
struct Edge {
int u, v;
Edge(int u = , int v = ) : u(u), v(v) {}
};
void init() {
bcc = tot = ;
clr(dfn, );clr(col, ); clr(fa, -);
rp(i, , n) G[i].clear(), bl[i].clear();
}
stack<Edge> stk;
void Tarjan(int u, int fa) {
low[u] = dfn[u] = ++tot;
rp(i, , G[u].size()) {
int v = G[u][i];
if (v == fa) continue;
Edge e = Edge(u, v);
if (!dfn[v]) {
stk.push(e);
Tarjan(v, u);
low[u] = min(low[v], low[u]);
if (low[v] >= dfn[u]) { //割点
bcc++;
BCC[bcc].clear();
while (true) { //将栈中所有属于当前点双连通分量的点全部标记,注意,栈内存的是边
Edge x = stk.top(); stk.pop();
int st = x.u, ed = x.v;
if (col[st] != bcc) {
BCC[bcc].pb(st); //将u加入当前点双连通分量的节点集
col[st] = bcc; //标记u点当前所述的点双连通分量编号,防止在遍历同一点双连通分量的过程中重复将点标记
bl[st].pb(bcc); //一个点可能属于多个点双连通分量,bl[u]存储的是u点所属的多个点双连通分量
}
if (col[ed] != bcc) {
BCC[bcc].pb(ed);
col[ed] = bcc;
bl[ed].pb(bcc);
}
if (st == u && ed == v) break;
}
}
} else if (dfn[v] < dfn[u]) {
stk.push(e);
low[u] = min(low[u], dfn[v]);
}
}
}
int find(int i) {
if (fa[i] == -) return i;
return fa[i] = find(fa[i]);
}
int main() {
int ncase = ;
while (~scanf("%d%d%d", &n, &m, &q) && n) {
init();
while (m--) {
int u, v;
scanf("%d%d", &u, &v);
G[u].pb(v), G[v].pb(u); u = find(u), v = find(v); //并查集加边
if (u != v) fa[u] = v;
}
rp(i, , n) if (!dfn[i]) Tarjan(i, -);
printf("Case %d:\n", ++ncase);
while (q--) {
int u, v;
scanf("%d%d", &u, &v);
if (find(u) != find(v)) printf("zero\n"); //如果这两点不连通,直接输出0
else {
bool flag = false;
for (int i = ; i < bl[u].size() && !flag; i++) //遍历u和v所属的点双连通分量点集,判断是否有点双连通分量同时包含u和v
for (int j = ; j < bl[v].size() && !flag; j++) {
if (bl[u][i] == bl[v][j]) { //如果存在这样的点双连通分量
int ord = bl[u][i]; // ord代表该点双连通分量的编号
if (BCC[ord].size() > ) //要如果该点双连通分量中点数>2,才能说明u和v之间一定有2条即两条以上的道路
puts("two or more"), flag = true;
}
}
if (!flag) puts("one"); //如果不存在点数>2的点双连通分量同时包含u和v,则说明u和v之间只有一条边相连
}
}
}
}

2018-12-02

HDU 3749 Financial Crisis (点双连通+并查集)的更多相关文章

  1. HDU 3749 Financial Crisis(点-双连通分量)

    Because of the financial crisis, a large number of enterprises go bankrupt. In addition to this, oth ...

  2. HDU 3749 Financial Crisis 经济危机(点双连通分量)

    题意: 给一个图n个点m条边(不一定连通),接下来又q个询问,询问两个点是为“不相连”,“仅有一条路径可达”,“有两条及以上的不同路径可达”三种情况中的哪一种.注:两条以上的路径指的是路径上的点连1个 ...

  3. HDU 3749 Financial Crisis

    Financial Crisis 题意:给一个图,包含N ( 3 <= N <= 5000 )个点, M ( 0 <= M <= 10000 )条边 and Q ( 1 < ...

  4. HDU 1598 find the most comfortable road 并查集+贪心

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1598 find the most comfortable road Time Limit: 1000 ...

  5. HDU 1116 Play on Words(欧拉回路+并查集)

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1116 Play on Words Time Limit: 10000/5000 MS (Java/Ot ...

  6. BZOJ4998 星球联盟(LCT+双连通分量+并查集)

    即要求动态维护边双.出现环时将路径上的点合并即可.LCT维护.具体地,加边成环时makeroot+access+splay一套把这段路径提出来,暴力dfs修改并查集祖先,并将这部分与根断开,视为删除这 ...

  7. ACM: hdu 1811 Rank of Tetris - 拓扑排序-并查集-离线

    hdu 1811 Rank of Tetris Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & % ...

  8. HDU(1856),裸的带权并查集

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1856 题意:朋友圈问题,A和B是朋友,B和C是朋友则A和C也是朋友,依次类推,题目的意思就是求最大的朋 ...

  9. HDU 1213 How Many Tables(模板——并查集)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1213 Problem Description Today is Ignatius' birthday ...

随机推荐

  1. Confluence 6 注册外部小工具

    你可以从外部站点中注册小工具(Gadget)(例如 Jira 应用),你注册成功的小工具将会在 宏浏览器中显示出来,使用你 Confluence 站点的用户可以使用 Gadget Macro 来调用它 ...

  2. Confluence 6 基于 Confluence 数据中心的 SAML 单点登录

    安全申明标记语言(Security Assertion Markup Language (SAML))是一个基于 XML 的数据格式,允许各个软件平台通过identity provider (IdP) ...

  3. ES6之Set与Map加深理解

    Set 类似于数组,但是成员的值都是唯一的,没有重复的值,有序. Set函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化. 用途 数组去重: [...new ...

  4. poj3417lca+树上差分

    /* 给定n个点的树,在其中加入m条新边(称为非树边) 现在可以割断一条树边,一条非树边,使图分裂成两个联通块,请问有几种切割方式 对树边进行分情况讨论 如果树边不处在环中,则割断这条树边后可以割断任 ...

  5. time与datetime模块

    在python中,通常用下面几种方式来表示时间: 时间戳(timestamp):通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量. 格式化的时间字符串(format s ...

  6. Centos6.8部署jumpserver(完整版)

    环境: 系统 Centos6.8 IP:192.168.66.131 关闭selinux和防火墙 # 修改字符集,否则可能报 input/output error的问题,因为日志里打印了中文 # lo ...

  7. 支持向量机-完整Platt-SMO算法加速优化

    完整版SMO算法与简单的SMO算法: 实现alpha的更改和代数运算的优化环节一模一样,唯一的不同就是选择alpha的方式.完整版应用了一些能够提速的方法. 同样使用Jupyter实现,后面不在赘述 ...

  8. python字符串之join

    函数:string.join() Python中有join()和os.path.join()两个函数,具体作用如下: join():连接字符串数组.将字符串.元组.列表中的元素以指定的字符(分隔符)连 ...

  9. Go中的panic和recover

    这两个内置函数,用来处理go的运行时错误. panic用来主动抛出错误, recover用来捕获panic抛出的错误. recover()和defer一起使用, 但是recover()只有在defer ...

  10. vue-app开发入门

    vue的中文文档在这里 1. 简单地引用vue.js 使用vue框架最简单的方式就是写一个HTML页面然后引用vue.js啦. 使用<script> 标签就可以将vue.js导入并且使用它 ...