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  islands, numbered from  to . There are  bridges in the kingdom, among which the -th bridge connects the -th island and the -th island. The knights can go through each bridge in both directions.

Landing separately on the -th and the -th island, the two knights start their journey heading to the -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 -th island and leads to the -th island, while the other starts from the -th island and also leads to the -th island.

As the princess is caught very often, the knights will ask you for help  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.

题意

意识到首先可以进行缩点,图中所有的桥将整个图分成了数个联通快,联通块内的点之间一定有至少两条路可以相互到达。

用Tarjan求出所有的桥,缩点之后意识到整个图变成了一片森林(如果保证图联通就是一颗树),可以发现如果存在合理的路,终点所在的点一定在两个骑士的起点中间,类似 的情况,三角形是终点,当然三个点之间可以插入任意个点。

那问题就变成了判断一棵树上一个点是否在两个点中间的情况,意识到情况只有两种情况(u,v为起点,标三角形的为终点),利用lca的方式判断是否满足这两种情况即可,不满足即为NO

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 2e5 + ;
const int maxm = 4e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
struct Edge{
int to,next;
bool cut;
}edge[maxm * ];
int head[maxn],tot;
const int SP = ;
int pa[maxn][SP],dep[maxn];
int scc[maxn];
vector<int>P[maxn];
int ind[maxn];
int low[maxn],dfn[maxn],Stack[maxn],Index,top;
bool Instack[maxn];
int fa[maxn],fa2[maxn];
void add(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
edge[tot].cut = ;
head[u] = tot++;
}
void Tarjan(int u,int pre){
int v;
low[u] = dfn[u] = ++Index;
Stack[top++] = u;
Instack[u] = true;
int son = ;
int pre_cnt = ;
for(int i = head[u]; ~i; i = edge[i].next){
int v = edge[i].to;
if(v == pre && pre_cnt == ){
pre_cnt++;
continue;
}
if(!dfn[v]){
son++;
Tarjan(v,u);
if(low[u] > low[v]) low[u] = low[v];
if(low[v] > dfn[u]){
edge[i].cut = edge[i ^ ].cut = true;
}
}else if(low[u] > dfn[v]){
low[u] = dfn[v];
}
}
Instack[u] = false;
top--;
}
int find(int x){
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
int find2(int x){
if(x == fa2[x]) return x;
return fa2[x] = find2(fa2[x]);
}
void Union2(int a,int b){
a = find2(a); b = find2(b);
fa2[a] = b;
}
void Union(int a,int b){
a = find(a) ; b = find(b);
fa[a] = b;
}
bool vis[maxn];
void dfs(int u,int la){
pa[u][] = la; dep[u] = dep[la] + ;
for(int i = ; i < SP; i ++) pa[u][i] = pa[pa[u][i - ]][i - ];
for(int i = ; i < P[u].size(); i ++){
int v = P[u][i];
if(v == la) continue;
dfs(v,u);
}
}
int lca(int u,int v){
if(dep[u] < dep[v]) swap(u,v);
int t = dep[u] - dep[v];
for(int i = ; i < SP; i ++) if(t & ( << i)) u = pa[u][i];
for(int i = SP - ; i >= ; i --){
int uu = pa[u][i],vv = pa[v][i];
if(uu != vv){
u = uu; v = vv;
}
}
return u == v?u:pa[u][];
}
vector<PII>E;
int main(){
int T; Sca(T);
while(T--){
N = read(),M = read(),K = read();
E.clear();
for(int i = ; i <= N ; i ++){
vis[i] = low[i] = dfn[i] = Instack[i] = ;
head[i] = -;
fa2[i] = fa[i] = i;
}
Index = top = tot = ;
for(int i = ; i <= M ; i ++){
int u = read(),v = read();
add(u,v); add(v,u);
} for(int i = ; i <= N ; i ++) if(!dfn[i]) Tarjan(i,i);
for(int i = ; i <= N ; i ++){
for(int j = head[i]; ~j ; j = edge[j].next){
int v = edge[j].to;
if(!edge[j].cut) Union(i,v);
else E.pb(mp(i,v));
Union2(i,v);
}
}
int cnt = ;
for(int i = ; i <= N ; i ++){
if(fa[i] == i) scc[++cnt] = i;
}
for(int i = ; i < E.size(); i ++){
if(E[i].fi <= E[i].se) continue;
int a = find(E[i].fi),b = find(E[i].se);
if(a == b) continue;
P[a].pb(b); P[b].pb(a);
}
for(int i = ; i <= N ; i ++){
int x = find2(scc[i]);
if(!vis[x]){
vis[x] = ;
dep[scc[i]] = ;
dfs(scc[i],);
}
}
for(int i = ; i <= K; i ++){
int w = read(),u = read(),v = read();
int pw = find2(w),pu = find2(u),pv = find2(v);
if(pw != pu || pw != pv){
puts("No"); continue;
}
int fw = find(w),fu = find(u),fv = find(v);
if(dep[fu] > dep[fv]) swap(fu,fv);
if(fw == fv || fu == fw){
puts("Yes");
continue;
}
int l = lca(fu,fv);
if(lca(fv,fw) == fw && lca(fw,fu) == fu){
puts("Yes");
continue;
}
if(lca(fw,l) == l && (lca(fv,fw) == fw || lca(fu,fw) == fw)){
puts("Yes");
continue;
}
puts("No");
}
for(int i = ; i <= cnt ; i ++) P[scc[i]].clear();
}
return ;
}

The 19th Zhejiang University Programming Contest - H的更多相关文章

  1. The 19th Zhejiang University Programming Contest Sponsored by TuSimple (Mirror)

    http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=391 A     Thanks, TuSimple! Time ...

  2. 2019 The 19th Zhejiang University Programming Contest

    感想: 今天三个人的状态比昨天计院校赛的状态要好很多,然而三个人都慢热体质导致签到题wa了很多发.最后虽然跟大家题数一样(6题),然而输在罚时. 只能说,水题还是刷得少,看到签到都没灵感实在不应该. ...

  3. The 19th Zhejiang University Programming Contest Sponsored by TuSimple (Mirror) B"Even Number Theory"(找规律???)

    传送门 题意: 给出了三个新定义: E-prime : ∀ num ∈ E,不存在两个偶数a,b,使得 num=a*b;(简言之,num的一对因子不能全为偶数) E-prime factorizati ...

  4. zoj 4020 The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light(广搜)

    题目链接:The 18th Zhejiang University Programming Contest Sponsored by TuSimple - G Traffic Light 题解: 题意 ...

  5. The 16th Zhejiang University Programming Contest-

    Handshakes Time Limit: 2 Seconds      Memory Limit: 65536 KB Last week, n students participated in t ...

  6. The 18th Zhejiang University Programming Contest Sponsored by TuSimple -C Mergeable Stack

    题目链接 题意: 题意简单,就是一个简单的数据结构,对栈的模拟操作,可用链表实现,也可以用C++的模板类来实现,但是要注意不能用cin cout,卡时间!!! 代码: #include <std ...

  7. The 18th Zhejiang University Programming Contest Sponsored by TuSimple

    Pretty Matrix Time Limit: 1 Second      Memory Limit: 65536 KB DreamGrid's birthday is coming. As hi ...

  8. ZOJ 4016 Mergeable Stack(from The 18th Zhejiang University Programming Contest Sponsored by TuSimple)

    模拟题,用链表来进行模拟 # include <stdio.h> # include <stdlib.h> typedef struct node { int num; str ...

  9. The 17th Zhejiang University Programming Contest Sponsored by TuSimple A

    Marjar Cola Time Limit: 1 Second      Memory Limit: 65536 KB Marjar Cola is on sale now! In order to ...

随机推荐

  1. git在本地向远程仓库创建分支

    在本地的仓库种,如果想给upstream创建新分支并关联,需要执行 git push -u/--set-upstream 远程仓库名 远程分支名

  2. C#多线程和线程池 【转】

    1.概念  1.0 线程的和进程的关系以及优缺点 windows系统是一个多线程的操作系统.一个程序至少有一个进程,一个进程至少有一个线程.进程是线程的容器,一个C#客户端程序开始于一个单独的线程,C ...

  3. Window10上安装Redis及其客户端

    资源下载地址 Redis安装包:https://github.com/MicrosoftArchive/redis/releases Redis客户端: 链接:https://pan.baidu.co ...

  4. iOS 类方法 、野指针与空指针

    一.类方法: 不依赖于对象,执行效率更高; 能用类方法解决的问题,尽量使用类方法; 类方法中不能直接访问实例变量(成员变量) 二.野指针和空指针是什么?什么时候产生?怎么避免? 只要一个对象被释放了, ...

  5. anaconda的scikit-learn报错It seems that scikit-learn has not been built

    我们在导入sklearn时往往会报错. import sklearn Traceback (most recent call last): File "<stdin>" ...

  6. java jdk动态代理(proxy)

    1. 涉及主要jdk api java.lang.reflect.InvocationHandler: public interface InvocationHandler { /** * Proce ...

  7. 【憩园】C#并发编程之异步编程(一)

    写在前面 C#5.0中,对异步编程进行了一次革命性的重构,引入了async和await这两个关键字,使得开发人员在不需要深刻了解异步编程的底层原理,就可以写出十分优美而又代码量极少的代码.如果使用得当 ...

  8. css3动画和animate.css动画库使用

    CSS3动画 css3动画可以分为两种.transition过渡动画和keyframes关键帧动画 过渡动画 第一种叫过渡(transition)动画,就是从初始状态过渡到结束状态这个过程中所产生的动 ...

  9. “Axure”介绍

    一. Axure RP简介: Axure RP 能帮助网站需求设计者,快捷而简便的创建基于网站构架图的带注释页面示意图.操作流程图.以及交互设计,并可自动生成用于演示的网页文件和规格文件,以提供演示与 ...

  10. vue动态设置初始页