题目大意
给你一个
n
个点,
范围
(1 ≤ n ≤ 3∗105,0 ≤ m ≤ 3∗105)
思路
易得,如果一个环上有宝藏,那么我一定可以从环上的一个点进去,拿到宝藏,然后从任意一个点出来。那么我就可以缩环,建树,现在的树就是一颗某些点有宝藏,某些边有宝藏了,那我就求一下
a
到
参考代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 600005
#define maxsq 30
using namespace std;
int n,m,S,T;
int head[maxn],t[maxn * 2],vv[maxn * 2],next[maxn * 2],sum;
void insert(int x,int y,int z){
t[++sum]=y;
next[sum]=head[x];
vv[sum]=z;
head[x]=sum;
}
int dfn[maxn],low[maxn],scc,cnt;
int instack[maxn],sta[maxn],top,belong[maxn];
int fr[maxn],ok[maxn];
int head2[maxn],t2[2*maxn],next2[2*maxn],sum2,v2[maxn*2];
void insert2(int x,int y,int z){
t2[++sum2]=y;
next2[sum2]=head2[x];
v2[sum2]=z;
head2[x]=sum2;
}
void Tarjan(int u,int fa)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
instack[u]=1;
for(i=head[u];i;i=next[i])
{
v=t[i];
if(i==(fa^1))
continue;
if(!dfn[v])
{
fr[v]=i;
Tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
scc++;
while(1)
{
v=sta[top--];
instack[v]=0;
belong[v]=scc;
if(v==u)
break;
}
}
}
int fa[maxn][maxsq][2],deep[maxn];
void maketree(int x,int father){
deep[x]=deep[father]+1;
for(int tmp=head2[x];tmp;tmp=next2[tmp]) {
if (t2[tmp]==father) continue;
fa[t2[tmp]][0][0]=x;
fa[t2[tmp]][0][1]=(ok[x]) || (ok[t2[tmp]]) || (v2[tmp]);
maketree(t2[tmp],x);
}
}
bool getlca(int x,int y){
if (deep[x]<deep[y]) swap(x,y);
fd(i,20,0)
if (deep[fa[x][i][0]]>=deep[y]) {
if (fa[x][i][1]) return 1;
x=fa[x][i][0];
}
if (x==y) return 0;
fd(i,20,0)
if (fa[x][i][0]!=fa[y][i][0]) {
if (fa[x][i][1]) return 1;
if (fa[y][i][1]) return 1;
x=fa[x][i][0];
y=fa[y][i][0];
}
if (fa[x][0][1]) return 1;
if (fa[y][0][1]) return 1;
return 0;
}
int main(){
sum=1;
scanf("%d%d",&n,&m);
fo(i,1,m) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
insert(y,x,z);
}
fo(i,1,n)
if (dfn[i]==0) Tarjan(i,0);
fo(i,1,n) {
for(int tmp=head[i];tmp;tmp=next[tmp]) {
if (belong[t[tmp]]==belong[i]) {
if (vv[tmp]) ok[belong[i]]=1;
continue;
}
insert2(belong[i],belong[t[tmp]],vv[tmp]);
}
}
maketree(1,0);
fa[1][0][0]=1;
fa[1][0][1]=ok[1];
fo(i,1,20)
fo(j,1,scc) fa[j][i][0]=fa[fa[j][i-1][0]][i-1][0],fa[j][i][1]=fa[j][i-1][1] || fa[fa[j][i-1][0]][i-1][1];
scanf("%d%d",&S,&T);
if (ok[belong[S]]||ok[belong[T]]) {
puts("YES");
return 0;
}
if (getlca(belong[S],belong[T])) {
puts("YES");
} else puts("NO");
return 0;
}