【trick&&吐槽】
1,缩环重建图的时候一定要注意映射关系。
【题意】
有n(3e5)个点,m(3e5)条双向边(xi,yi,zi)。
没有重边没有自环(这个条件其实无所谓)
有些边是特殊的边(zi==1)
每条边只能经过一次
问你我们能否有一条路径,使得我们可以从ST出发到达ED
【类型】
双连通分量tarjan缩环
BFS
【分析】
这题思考起来有些不着边际。
关键信息是——一条边只能经过一次。
什么情况下一条边我们会经过多次呢?
经过多次必然形成了环。
于是,介于这个图是无向图,我们可以考虑先双连通缩环。
如果ST和ED在同一个联通块内,且这个联通块内有special edge 显然答案为YES
否则的话,已经缩环之后的图,ST与ED之前肯定只有单一路径可达,每个点只会入栈一次,被更新一次,于是直接做BFS即可。
1,缩环重建图的时候一定要注意映射关系。
【题意】
有n(3e5)个点,m(3e5)条双向边(xi,yi,zi)。
没有重边没有自环(这个条件其实无所谓)
有些边是特殊的边(zi==1)
每条边只能经过一次
问你我们能否有一条路径,使得我们可以从ST出发到达ED
【类型】
双连通分量tarjan缩环
BFS
【分析】
这题思考起来有些不着边际。
关键信息是——一条边只能经过一次。
什么情况下一条边我们会经过多次呢?
经过多次必然形成了环。
于是,介于这个图是无向图,我们可以考虑先双连通缩环。
如果ST和ED在同一个联通块内,且这个联通块内有special edge 显然答案为YES
否则的话,已经缩环之后的图,ST与ED之前肯定只有单一路径可达,每个点只会入栈一次,被更新一次,于是直接做BFS即可。
就AC啦!
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define L(i) i<<1
#define R(i) i<<1|1
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-12
#define maxn 300100
#define MOD 1000000007
struct Edge
{
int to,next,val;
} edge[maxn<<1];
int n,m;
int tot,head[maxn],scc;
int dfn[maxn],low[maxn],time;
int sta[maxn],top,S,E,instack[maxn];
int belong[maxn],tmp[maxn];
vector<pair<int,int> > a[maxn];
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void add_edge(int u,int v,int cnt)
{
edge[tot].to = v;
edge[tot].val = cnt;
edge[tot].next = head[u];
head[u] = tot++;
}
void tarjan(int u,int pre)
{
dfn[u] = low[u] = time++;
sta[++top] = u;
instack[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(v == pre)
continue;
if(!dfn[v])
{
tarjan(v,u);
low[u] = min(low[u],low[v]);
}
else if(instack[v])
low[u] = min(low[u],dfn[v]);
}
if(dfn[u] == low[u])
{
tmp[++scc] = 0;
a[scc].clear();
while(1)
{
int v = sta[top--];
instack[v] = 0;
belong[v] = scc;
if(v == u)
break;
}
}
}
int bfs()
{
memset(instack,0,sizeof(instack));
queue<int> q;
q.push(belong[S]);
instack[belong[S]] = 1;
while(!q.empty())
{
int u = q.front();
q.pop();
for(int i = a[u].size() - 1; i >= 0; i--)
{
int v = a[u][i].first;
int tp = a[u][i].second;
if(instack[v])
continue;
tmp[v] |= tmp[u];
tmp[v] |= tp;
q.push(v);
instack[v] = 1;
}
}
return tmp[belong[E]];
}
int solve()
{
for(int u = 1; u <= n; u++)
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(belong[u] == belong[v])
tmp[belong[u]] |= edge[i].val;
a[belong[u]].push_back(make_pair(belong[v],edge[i].val));
}
if(belong[S] == belong[E] && tmp[belong[S]])
return 1;
return bfs();
}
int main()
{
int t;
while(scanf("%d%d",&n,&m) != EOF)
{
init();
for(int i = 0; i < m; i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add_edge(x,y,z);
add_edge(y,x,z);
scanf("%d%d",&S,&E);
top = 0;
time = scc = 0;
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
tarjan(1,0);
printf("%s\n",solve()?"YES":"NO");
}
}
return 0;
}