HDU 3749 Financial Crisis 经济危机(点双连通分量)
题意:
给一个图n个点m条边(不一定连通),接下来又q个询问,询问两个点是为“不相连”,“仅有一条路径可达”,“有两条及以上的不同路径可达”三种情况中的哪一种。注:两条以上的路径指的是路径上的点连1个点也不重复。
思路:并查集+tarjan求割点。
(1)情况一:先并查集处理,如果两个点从一开始就不连通,直接输出zero
(2)情况二和情况三:两点既然连通,那么可能是只有1条路径,比如中间隔着一个割点;也可能有多条路径,比如在同一个双连通分量内。那么直接判断其是否在同一个双连通分量内即可,若在同一个双连通分量内,那么路径起码有2条不重复的。
并查集算法看其他题目。
tarjan用刘汝佳那个版本。只是我用了unordered_set来存储双连通分量,对于每个询问就在每个双连通分量中查是否同时存在(因为其中一个可能是割点),若同时存在且size>2才是输出 two or more。
具体实现看代码。
#include <bits/stdc++.h>
using namespace std;
const int N=+;
stack< pair<int,int> > stac; //tarjan用的栈
vector<int> vect[N]; //图
unordered_set<int> bi[N]; //双连通分量 int pre[N]; //并查集用的,保存领导 int find(int x) //查
{
return pre[x]==x? x: pre[x]=find(pre[x]);
} void joint(int x,int y) //并
{
x=find(x);
y=find(y);
if(x!=y) pre[x]=y;
} int dfn[N], low[N];
int bccno[N];
int cnter, bcc_cnt; void DFS(int x, int far)
{
dfn[x]= low[x]= ++cnter;
int chd=; //孩子
for(int i=; i<vect[x].size(); i++)
{
int t=vect[x][i]; if(!dfn[t]) //树边
{
chd++;
stac.push(make_pair(x,t)); //进栈
DFS(t,x);
low[x]=min(low[x],low[t]);
//if((far&&low[t]>=dfn[x]) || (!far&&chd>1) ) //割点
if(low[t]>=dfn[x] ) //割点。如果根只有0或1个孩子呢?那根就不是连通分量中的一个点。
{
bi[++bcc_cnt].clear(); //连通分量
while()
{
int a=stac.top().first;
int b=stac.top().second;
stac.pop();
if(bccno[a]!=bcc_cnt)
{
bccno[a]=bcc_cnt;
bi[bcc_cnt].insert(a);
}
if(bccno[b]!=bcc_cnt)
{
bccno[b]=bcc_cnt;
bi[bcc_cnt].insert(b);
}
if(a==x && b==t) break;
}
}
}
else if(dfn[t]<dfn[x] && t!=far)
{
stac.push(make_pair(x,t)); //进栈
low[x]=min(low[x],dfn[t]);
}
}
} int cal_bcc(int n)
{
memset(bccno,,sizeof(bccno));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low)); while(!stac.empty()) stac.pop(); bcc_cnt= cnter=;
for(int i=n; i>; i--)
if(!dfn[i]) DFS(i,);
} int check(int n,int a, int b)
{
if(find(a)!=find(b)) return ; //不连通 for(int i=; i<=bcc_cnt; i++)
{
if(bi[i].find(a)!=bi[i].end() && bi[i].find(b)!=bi[i].end() && bi[i].size()>) //对于只有两个点的双连通分量,仅有1条边,输出one。
{
printf("two or more\n");
return ;
}
}
printf("one\n");
return ;
} void init(int n)
{
memset(pre,,sizeof(pre));
for(int i=; i<=n; i++) vect[i].clear();
for(int i=; i<=n; i++) pre[i]=i;
} int main()
{
freopen("input.txt", "r", stdin);
int n, m, q, a, b, j=;
while(scanf("%d%d%d",&n, &m, &q), n+m+q)
{
init(n);
for(int i=; i<m; i++)
{
scanf("%d%d", &a, &b);
vect[++a].push_back(++b);
vect[b].push_back(a);
joint(a,b); //并查集
} cal_bcc(n); //tarjan算法
printf("Case %d:\n",++j);
/*
for(int i=1; i<=bcc_cnt; i++) //输出每个双连通分量。
{
printf("第%d个双连通分量包含以下点:",i);
for(unordered_set<int>::iterator it=bi[i].begin(); it!=bi[i].end();it++)
{
printf("%d ",*it);
}
printf("\n");
}
*/
for(int i=; i<q; i++)
{
scanf("%d%d", &a, &b);
if(!check(n, ++a, ++b)) printf("zero\n");
}
}
return ;
}
AC代码
HDU 3749 Financial Crisis 经济危机(点双连通分量)的更多相关文章
- HDU 3749 Financial Crisis(点-双连通分量)
Because of the financial crisis, a large number of enterprises go bankrupt. In addition to this, oth ...
- HDU 3749 Financial Crisis (点双连通+并查集)
<题目连接> 题目大意: 给你一个(保证输入无重边,无自环)无向图,然后有下面Q条询问,每条询问为:问你u点与v点之间有几条(除了首尾两点外,其他点不重复)的路径.如果有0条或1条输出0或 ...
- HDU 3749 Financial Crisis
Financial Crisis 题意:给一个图,包含N ( 3 <= N <= 5000 )个点, M ( 0 <= M <= 10000 )条边 and Q ( 1 < ...
- HDU 4612——Warm up——————【边双连通分量、树的直径】
Warm up Time Limit:5000MS Memory Limit:65535KB 64bit IO Format:%I64d & %I64u Submit Stat ...
- Warm up HDU - 4612( 树的直径 边双连通分量)
求在图中新建一条边后 剩下的最少的桥的数量..先tarjan求桥的数量..然后缩点..以连通分量为点建图 bfs求直径 最后用桥的数量减去直径即为答案 bfs求直径 https://www.cnb ...
- hdu Caocao's Bridges(无向图边双连通分量,找出权值最小的桥)
/* 题意:给出一个无向图,去掉一条权值最小边,使这个无向图不再连同! tm太坑了... 1,如果这个无向图开始就是一个非连通图,直接输出0 2,重边(两个节点存在多条边, 权值不一样) 3,如果找到 ...
- HDU 5458 Stability(双连通分量+LCA+并查集+树状数组)(2015 ACM/ICPC Asia Regional Shenyang Online)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 Problem Description Given an undirected connecte ...
- HDU 2242 考研路茫茫——空调教室(边双连通分量+树形dp+重边标号)
http://acm.hdu.edu.cn/showproblem.php?pid=2242 题意: 思路:首先求一下双连通分量,如果只有一个双连通分量,那么无论断哪根管子,图还是连通的. 最后只需要 ...
- hdu 2460(tarjan求边双连通分量+LCA)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2460 思路:题目的意思是要求在原图中加边后桥的数量,首先我们可以通过Tarjan求边双连通分量,对于边 ...
随机推荐
- HDU 4587 TWO NODES 割点
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4587 题意: 删除两个点,使连通块的数目最大化 题解: 枚举删除第一个点,然后对删除了第一个点的图跑 ...
- Eclipse 创建Maven工程
前言 开发环境 sts-3.7.2.RELEASE 创建步骤 1.开启eclipse,右键new——>other,如下图找到maven project 2.选择maven project,显示创 ...
- Jquery 判断浏览器类型
$(function() { //FireFox2及以上 if ($.browser.MozillaSideBar && $.browser.version >= "1 ...
- 《深入理解javascript原型和闭包系列》 知识点整理(转)
深入理解javascript原型和闭包系列 对原型和闭包等相关知识的讲解,由浅入深,通俗易懂,每个字都值得细细研究. 一.一切都是对象 1. typeof操作符输出6种类型:string boolea ...
- H5下拉刷新特效demo,动画流畅
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- 【BZOJ】【2818】Gcd
欧拉函数/莫比乌斯函数 嗯……跟2190很像的一道题,在上道题的基础上我们很容易就想到先求出gcd(x,y)==1的组,然后再让x*=prime[i],y*=prime[i]这样它们的最大公约数就是p ...
- matlab字符串操作总结
matlab字符串操作总结 字符串操作总结 char(S1,S2,…)利用给定的字符串或单元数组创建字符数组double(S)将字符串转化成ASC码形式cellstr(S)利用的给定的字符数组创建字符 ...
- c++中new和delete的使用方法
c++中new和delete的使用方法 new和delete运算符用于动态分配和撤销内存的运算符 new用法: 1. 开辟单变量地址空间 1)new int; //开辟一个存放数组的存储空间 ...
- 140227项目开发及上线过程遇到的10个问题(重点: FCK过滤替换)
1.替换条件判断问题 String s = (String)map2.get("contentIntro"); if(s != null && s.length() ...
- 设计模式(Design Patterns——可复用面向对象软件的基础
设 计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代 码可靠性. 毫无疑问 ...