一、题目
二、解法
首先对于一个边双连通分量,在某两点的路径中,每个边都有方案能经过。因为边双保证了两点间有两条边完全不等的路径,那么先从当前点走到目标边,还能走到目标点。
那么先缩点,由于只有一次询问,那么暴力爬山即可。
#include <cstdio>
#include <vector>
#include <stack>
using namespace std;
const int M = 300005;
const int MOD = 1e9+7;
int read()
{
int x=0,f=1;char c;
while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
return x*f;
}
int n,m,q,tot,cnt,Index,f[M],dep[M],fa[M],c[M];
int dfn[M],low[M],in[M],col[M],pd[M],a[M],b[M],w[M];
stack<int> s;vector<int> g[M];
struct edge
{
int v,c,next;
}e[2*M];
void dfs(int u,int p)
{
dfn[u]=low[u]=++Index;
in[u]=1;s.push(u);
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==p) continue;
if(!dfn[v])
{
dfs(v,u);
low[u]=min(low[u],low[v]);
}
else if(in[v])
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
cnt++;
int v=0;
do
{
v=s.top();s.pop();
col[v]=cnt;in[v]=0;
}while(v!=u);
}
}
void dfs1(int u,int p)
{
fa[u]=p;
dep[u]=dep[p]+1;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==p) continue;
c[v]=e[i].c;
dfs1(v,u);
}
}
signed main()
{
n=read();m=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),c=read();
a[i]=u;b[i]=v;w[i]=c;
e[++tot]=edge{v,c,f[u]},f[u]=tot;
e[++tot]=edge{u,c,f[v]},f[v]=tot;
}
dfs(1,0);
tot=0;
for(int i=1;i<=n;i++)
f[i]=0;
for(int i=1;i<=m;i++)
{
if(col[a[i]]==col[b[i]])
pd[col[a[i]]]|=w[i];
else
{
int u=col[a[i]],v=col[b[i]];
e[++tot]=edge{u,w[i],f[v]},f[v]=tot;
e[++tot]=edge{v,w[i],f[u]},f[u]=tot;
}
}
dfs1(1,0);
int ans=0,u=col[read()],v=col[read()];
while(u^v)
{
if(dep[u]<dep[v]) swap(u,v);
ans|=pd[u];
ans|=c[u];
u=fa[u];
}
ans|=pd[u];
if(ans) puts("YES");
else puts("NO");
}