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 ...
随机推荐
- 《创业者技能树》--创业课--14天复盘第一课candy2--HHR计划
1,厉害的人是如何分析问题的?
- 模块学习-shutil
高级的 文件.文件夹.压缩包 处理模块 shutil.copyfileobj(fsrc, fdst[, length]) 将文件内容拷贝到另一个文件中,可以部分内容 shutil.copyfile(s ...
- 解决chrome记住账号默认样式覆盖
当谷歌游览器记住账号后,输入框的颜色会变为黄色,最直接的方法:加入以下代码 input:-webkit-autofill , textarea:-webkit-autofill, select:-we ...
- !important面试汇总啊
https://www.jianshu.com/p/feab89b88d6b https://juejin.im/post/5c64d15d6fb9a049d37f9c20#heading-57
- 28 JavaScript语言类型&运算符
语言类型: 弱类型:可以改变变量值和对象类型 强类型:可以改变变量值不能改变对象类型 解释型:边编译边执行,速度慢.解释型一般是弱类型 编译型:先编译再执行(C++\Java),速度快.编译型一般是强 ...
- formValidation单个输入框值改变时校验
$("#tv_form").data("formValidation").updateStatus("pay.vcAmount", &qu ...
- ES6简单语法
ES6 简单语法: 变量声明 ES5 var 声明变量为全局变量 会变量提升 ES6 let 声明的变量为块级变量 且不能重复声明 不存在变量提升 # {}一个大括号为一个作用域 ES6 const ...
- HHR计划---作业复盘-直播第三课
一,出租车广告: 1,三个点不合格:周期太长了,大而全互联网产品,不符合MVP原则:业务关键点丢掉了:没有业务认知和成长. 2,关键假设: (1)车主有没有需求呀,画像怎么样? (2)车主收入如何,能 ...
- PAT T1016 Uniqueness of MST
dfs判断连通块的数量,prim算法建立最小生成树并判断是否唯一~ #include<bits/stdc++.h> using namespace std; ; const int inf ...
- Python组合类型笔记
Python中常用的三种组合数据类型,分别是: - 集合类型 - 序列类型 - 字典类型 1. 集合类型: -集合用大括号{}表示,元素间用逗号分隔 -建立集合类型用{}或set() -建立空集合类型 ...