博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
The 19th Zhejiang University Programming Contest - H
阅读量:5036 次
发布时间:2019-06-12

本文共 5633 字,大约阅读时间需要 18 分钟。

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 #include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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
#define PIL pair
#define PLL pair
#define pb push_back#define fi first#define se second typedef vector
VI;int read(){ int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){ if (c == '-') f = -1;c = getchar();}while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}const double eps = 1e-9;const int maxn = 2e5 + 10;const int maxm = 4e5 + 10;const int INF = 0x3f3f3f3f;const int mod = 1e9 + 7; int N,M,K;struct Edge{ int to,next; bool cut;}edge[maxm * 2];int head[maxn],tot;const int SP = 20;int pa[maxn][SP],dep[maxn];int scc[maxn];vector
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 = 0; head[u] = tot++;}void Tarjan(int u,int pre){ int v; low[u] = dfn[u] = ++Index; Stack[top++] = u; Instack[u] = true; int son = 0; int pre_cnt = 0; for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].to; if(v == pre && pre_cnt == 0){ 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 ^ 1].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][0] = la; dep[u] = dep[la] + 1; for(int i = 1; i < SP; i ++) pa[u][i] = pa[pa[u][i - 1]][i - 1]; for(int i = 0 ; 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 = 0 ; i < SP; i ++) if(t & (1 << i)) u = pa[u][i]; for(int i = SP - 1; i >= 0 ; i --){ int uu = pa[u][i],vv = pa[v][i]; if(uu != vv){ u = uu; v = vv; } } return u == v?u:pa[u][0];}vector
E;int main(){ int T; Sca(T); while(T--){ N = read(),M = read(),K = read(); E.clear(); for(int i = 0; i <= N ; i ++){ vis[i] = low[i] = dfn[i] = Instack[i] = 0; head[i] = -1; fa2[i] = fa[i] = i; } Index = top = tot = 0; for(int i = 1; i <= M ; i ++){ int u = read(),v = read(); add(u,v); add(v,u); } for(int i = 1; i <= N ; i ++) if(!dfn[i]) Tarjan(i,i); for(int i = 1; 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 = 0; for(int i = 1; i <= N ; i ++){ if(fa[i] == i) scc[++cnt] = i; } for(int i = 0 ; 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 = 1; i <= N ; i ++){ int x = find2(scc[i]); if(!vis[x]){ vis[x] = 1; dep[scc[i]] = 0; dfs(scc[i],0); } } for(int i = 1; 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 = 1; i <= cnt ; i ++) P[scc[i]].clear(); } return 0;}

 

转载于:https://www.cnblogs.com/Hugh-Locke/p/10707482.html

你可能感兴趣的文章
(转)Python3之os模块
查看>>
hdu 4038 stone
查看>>
ASP.NET 显示项目之外的图片
查看>>
2011数字图书馆前沿问题高级研讨班-学习笔记1
查看>>
深度学习系列 Part(3)
查看>>
HDFS之HBase伪分布安装
查看>>
android 测试----Monkey
查看>>
static 关键字
查看>>
Vue 的基本认识
查看>>
最高的分数
查看>>
命令别名设置: alias, unalias
查看>>
1051. 复数乘法 (15)
查看>>
gcc相关
查看>>
tmp目录
查看>>
Codeforces Round #374 (Div. 2)
查看>>
6个出色的基于JQuery的Tab选项卡实例
查看>>
(转)8款在线CSS优化工具/组织和压缩CSS
查看>>
删除文本文件行号的小方法(shell,sed)
查看>>
table头部、尾部固定;中间内容定高自适应滚动
查看>>
JAVA设计模式之调停者模式
查看>>