Day10 - A - Rescue the Princess ZOJ - 4097
Princess Cjb is caught by Heltion again! Her knights Little Sub and Little Potato are going to Heltion Kingdom to rescue her.
Heltion Kingdom is composed of nn islands, numbered from 11 to nn. There are mm bridges in the kingdom, among which the ii-th bridge connects the l_ili-th island and the r_iri-th island. The knights can go through each bridge in both directions.
Landing separately on the vv-th and the ww-th island, the two knights start their journey heading to the uu-th island where the princess is imprisoned. However, as the knights are fat and the bridges are unstable, there will be a risk of breaking down the bridge and falling into the water if they go through one or more common bridges during their journey.
Thus, to successfully bring back the princess, two paths \textbf{with no common bridges} are needed: one starts from the vv-th island and leads to the uu-th island, while the other starts from the ww-th island and also leads to the uu-th island.
As the princess is caught very often, the knights will ask you for help qq times. Each time, given their starting islands and their goal, you need to tell them whether it's possible to find two paths satisfying the constraints above.
Input
There are multiple test cases. The first line of the input contains an integer TT, indicating the number of test cases. For each test case:
The first line contains three integers nn, mm and qq (1 \le n \le 10^51≤n≤105, 0 \le m \le 2 \times 10^50≤m≤2×105, 1 \le q \le 10^51≤q≤105), indicating the number of islands, the number of bridges and the number of queries.
The following mm lines describe the bridges. The ii-th line contains two integers l_ili and r_iri (1 \le l_i,r_i \le n1≤li,ri≤n), indicating the two islands the ii-th bridge connects. Notice that different bridges may connect the same pair of islands and a bridge may connect an island to itself.
The following qq lines describe the queries. The ii-th line contains three integers u_iui, v_ivi and w_iwi (1 \le u_i,v_i,w_i \le n1≤ui,vi,wi≤n), indicating the island where the princess is imprisoned and the starting islands of the two knights.
It's guaranteed that the sum of nn of all test cases will not exceed 5 \times 10^55×105, the sum of mm of all test cases will not exceed 10^6106, and the sum of qq of all test cases will not exceed 5 \times 10^55×105.
Output
For each test case output qq lines indicating the answers of the queries. For each query, if two paths meeting the constraints can be found, output "Yes" (without quotes), otherwise output "No" (without quotes).
Sample Input
2
6 7 4
1 2
2 3
3 1
4 5
5 6
6 4
1 4
4 1 3
1 4 2
1 2 3
1 3 3
2 1 2
1 2
1 1 1
2 1 2
Sample Output
No
Yes
Yes
Yes
Yes
Yes
Hint
For the first sample test case:
- For the 2nd query, we can select the paths 4-1 and 2-1.
- For the 3rd query, we can select the paths 2-1 and 3-1.
- For the 4th query, we can select the paths 3-1 and 3-2-1.
For the second sample test case:
- For the 1st query, as the knights and the princess are on the same island initially, the answer is "Yes".
- For the 2nd query, as one of the knights are on the same island with the princess initially, he does not need to cross any bridge. The other knight can go from island 1 to island 2 directly.
思路:求两个点不同边路径,想到边双缩点,这题需要考虑重边和多个连通块,对每个连通块缩点,跑lca,判断lca即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<set>
#include<vector>
#include<map>
using namespace std;
#define lowbit(x) ((x)&(-x))
typedef long long LL;
typedef pair<LL, LL> PLL; const int maxm = 2e5+; int dfn[maxm], low[maxm], s[maxm], dfscnt, top, bcc, bccnum[maxm], block[maxm], father[maxm], blocknum, depth[maxm], grand[maxm][];
int vis[maxm], N;
struct Node {
int u, v;
}; vector<int> G[maxm], G2[maxm];
vector<Node> edges; void addedge(int u, int v) {
edges.push_back(Node{u, v});
G2[u].push_back(edges.size()-);
edges.push_back(Node{v, u});
G2[v].push_back(edges.size()-);
} void init(int n) {
for(int i = ; i <= n; ++i) G[i].clear(), G2[i].clear();
edges.clear();
dfscnt = top = ;
bcc = blocknum = ;
memset(vis, , sizeof(vis));
memset(block, , sizeof(block)), memset(father, , sizeof(father));
memset(dfn, , sizeof(dfn)), memset(low, , sizeof(low));
memset(bccnum, , sizeof(bccnum));
} void tarjan(int u, int fa) { //边双缩点
int v, k = , siz = G[u].size();
dfn[u] = low[u] = ++dfscnt;
s[++top] = u;
father[u] = fa;
for(int i = ; i < siz; ++i) {
v = G[u][i];
if(v == fa && !k) { // 判重边
k++;
continue;
}
if(!dfn[v]) {
tarjan(v, u);
low[u] = min(low[u], low[v]);
} else
low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u]) {
do {
v = s[top--];
bccnum[v] = bcc;
} while(u != v);
bcc++;
}
} void dfs1(int u) {
block[u] = blocknum;
int siz = G[u].size();
for(int i = ; i < siz; ++i) {
int v = G[u][i];
if(!block[v])
dfs1(v);
}
} void dfs2(int u, int fa) { // build lca tree
vis[u] = ;
depth[u] = depth[fa] + ;
grand[u][] = fa;
for(int i = ; i <= N; ++i)
grand[u][i] = grand[grand[u][i-]][i-];
int siz = G2[u].size();
for(int i = ; i < siz; ++i) {
int v = edges[G2[u][i]].v;
if(v != fa) {
dfs2(v, u);
}
}
} int lca(int a, int b) {
if(a == b) return a;
if(depth[a] > depth[b]) swap(a, b);
for(int i = N; i >= ; --i)
if(depth[a] <= depth[b] - (<<i)) b = grand[b][i];
if(a == b) return a;
for(int i = N; i >= ; --i) {
if(grand[a][i] == grand[b][i]) continue;
else {
a = grand[a][i], b = grand[b][i];
}
}
return grand[a][];
} void run_case() {
int n, m, q, u, v, w;
cin >> n >> m >> q;
init(n);
for(int i = ; i < m; ++i) {
cin >> u >> v;
G[u].push_back(v), G[v].push_back(u);
}
for(int i = ; i <= n; ++i) //找连通块
if(!block[i]) {
dfs1(i);
blocknum++;
}
for(int i = ; i <= n; ++i) // 缩点
if(!dfn[i])
tarjan(i, i);
N = floor(log(bcc + 0.0) / log(2.0)) + ; //最多能跳的2^i祖先
for(int i = ; i <= n; ++i) {
int v = father[i];
if(bccnum[i] != bccnum[v])
addedge(bccnum[i], bccnum[v]);
}
// build lca tree
for(int i = ; i < bcc; ++i) {
if(!vis[i]) {
dfs2(i, );
}
}
while(q--) {
cin >> u >> v >> w;
// 不同连通块
if(block[u] != block[v] || block[u] != block[w]) {
cout << "No" << "\n";
continue;
}
u = bccnum[u], v = bccnum[v], w = bccnum[w];
// 在同一连通块 不同点
if(u == v || u == w) {
cout << "Yes" << "\n";
continue;
}
if(v == w) {
cout << "No" << "\n";
continue;
}
int uv, uw, vw, uvw;
// u是vw的根即可
uv = lca(u, v), uw = lca(u, w), vw = lca(v, w), uvw = lca(uw, v);
if(vw == uvw && (uv == u || uw == u))
cout << "Yes" << "\n";
else
cout << "No" << "\n";
} } int main() {
ios::sync_with_stdio(false), cin.tie();
int t;
cin >> t;
while(t--)
run_case();
return ;
}
(自用板)
Day10 - A - Rescue the Princess ZOJ - 4097的更多相关文章
- H - Rescue the Princess ZOJ - 4097 (tarjan缩点+倍增lca)
题目链接: H - Rescue the Princess ZOJ - 4097 学习链接: zoj4097 Rescue the Princess无向图缩点有重边+lca - lhc..._博客园 ...
- sdut 2603:Rescue The Princess(第四届山东省省赛原题,计算几何,向量旋转 + 向量交点)
Rescue The Princess Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Several days ago, a b ...
- 山东省第四届acm.Rescue The Princess(数学推导)
Rescue The Princess Time Limit: 1 Sec Memory Limit: 128 MB Submit: 412 Solved: 168 [Submit][Status ...
- 计算几何 2013年山东省赛 A Rescue The Princess
题目传送门 /* 已知一向量为(x , y) 则将它旋转θ后的坐标为(x*cosθ- y * sinθ , y*cosθ + x * sinθ) 应用到本题,x变为(xb - xa), y变为(yb ...
- sdutoj 2603 Rescue The Princess
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2603 Rescue The Princess ...
- SDUT 2603:Rescue The Princess
Rescue The Princess Time Limit: 1000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 Several days ago, a b ...
- 2013山东省“浪潮杯”省赛 A.Rescue The Princess
A.Rescue The PrincessDescription Several days ago, a beast caught a beautiful princess and the princ ...
- 山东省赛A题:Rescue The Princess
http://acm.sdibt.edu.cn/JudgeOnline/problem.php?id=3230 Description Several days ago, a beast caught ...
- 山东省第四届ACM程序设计竞赛A题:Rescue The Princess
Description Several days ago, a beast caught a beautiful princess and the princess was put in prison ...
随机推荐
- idea 导入svn中java WEB项目
1.打开idea 2.填写svn路径 3.指定本地路径 4.选择1.8 format 5.添加jdk 6.配置tomcat启动项目 File -- Project Structure
- ModBus的小于3.5S间隔的理解
modbus协议中规定:至少3.5个字符传输时间的停顿间隔时间标志了消息的结束. 我的理解如下:约定参数:9600bps,8数据位,无奇偶校验,1起始位,1停止位. 9600bps代表在9600的波特 ...
- java 抛出异常与finally的混用对于语句块的执行顺序的影响
代码如下: package test1; public class EmbededFinally { public static void main(String args[]) { int resu ...
- SSD算法
SSD算法 2016 出的目标检测算法 SSD效果主要有三点: 1.多尺度 2.设置了多种宽高比的(anchor box)default box 3.数据增强 1.1 设置 default box ...
- Ubuntu新手指引-软件包apt命令使用
看到这个博客,你十有八九是刚接触Ubuntu,不知从何下手.Ubuntu社区虽然现在不活跃,但里有很多文,可以帮助你快速上手,比如Ubuntu中文社区新手指引. 软件包的管理常常涉及root权限,普通 ...
- Java直通车——类与对象篇
一.面向对象 教师节来临,一群小学生应召出黑板报,该怎样完成呢?对于一个小孩子来说,你告诉他:“我们要确定黑板报主题.明确内容要旨.搜寻具体内容.构思版面布局.画图和写字.安排人员后勤辅助.”他可能会 ...
- Python 之并发编程之线程下
七.线程局部变量 多线程之间使用threading.local 对象用来存储数据,而其他线程不可见 实现多线程之间的数据隔离 本质上就是不同的线程使用这个对象时,为其创建一个只属于当前线程的字典 拿空 ...
- log4j2 异步多线程打印日志
log4j2 异步多线程打印日志 Maven依赖 <dependency> <groupId>org.apache.logging.log4j</groupId> ...
- python中模块的制作
1.import 模块名 2.from 模块名 import 类名(或方法名或全局变量) 3.from 模块名 import * 导入模块名下的所有类名,方法,全局变量 4.from 模块名 im ...
- django annotate()的使用
https://www.zmrenwu.com/post/18/ 博客文章通常都有分类,有时候我们会看到分类名后面还跟着该分类下的文章数量.前面我们通过学习 django 博客开发入门教程搭建了一个小 ...