题意:有n个点,m条边,接下来有m条边,如果他是特殊边边长就为1,否则为0,求从ST到ED每条边最多经过一次能否经过任一特殊边。
思路:边双连通缩点,如果缩点之后的环中有特殊边,那么把这个点的值标记为1,否则为0,因为缩点之后会形成一棵树,所以任意两点之间如果有路径,那么一定是唯一的,而且这题的路径有要求是有上下级关系的路径,所以一个缩点之后一个简单的bfs就行了。
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf -0x3f3f3f3f
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
typedef __int64 ll;
const int maxn=300100;
typedef pair<int,int> PI;
struct Edge{
int from,next,to,num;
}e[maxn*2];
int tot,head[maxn];
int Index,top,DFN[maxn],Low[maxn],Stack[maxn],Belong[maxn];
int block;
bool Instack[maxn];
void init(){
tot=0;
mem1(head);
}
void addedge(int from,int to,int w){
e[tot].from=from;
e[tot].to=to;
e[tot].next=head[from];
e[tot].num=w;
head[from]=tot++;
}
void Tarjan(int u,int pre){
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
int pre_cnt=0;
for(int i=head[u];i!=-1;i=e[i].next){
v=e[i].to;
if(v==pre&&pre_cnt==0){
pre_cnt++;
continue;
}
if(!DFN[v]){
Tarjan(v,u);
if(Low[u]>Low[v])
Low[u]=Low[v];
}
else if(Instack[v]&&Low[u]>DFN[v])
Low[u]=DFN[v];
}
if(Low[u]==DFN[u]){
block++;
do{
v=Stack[--top];
Instack[v]=false;
Belong[v]=block;
}while(v!=u);
}
}
int num[maxn],vis[maxn];
void bfs(int st){
queue<int>Q;
Q.push(st);
vis[st]=1;
while(!Q.empty()){
int u=Q.front();
Q.pop();
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].to,w=e[i].num;
if(vis[v]==0){
num[v]=max(num[v],num[u]+w);
vis[v]=1;
Q.push(v);
}
}
}
}
void solve(int n,int st,int ed){
mem0(DFN);
mem0(vis);
memset(Instack,false,sizeof(Instack));
Index=top=block=0;
for(int i=1;i<=n;i++)
if(!DFN[i])
Tarjan(i,0);
int tot1=tot;
init();
for(int i=0;i<tot1;i++){
int u=Belong[e[i].from],v=Belong[e[i].to];
if(u==v)
num[u]|=e[i].num;
else
addedge(u,v,e[i].num);
}
bfs(Belong[st]);
if(vis[Belong[ed]]==1&&num[Belong[ed]]!=0)
printf("YES\n");
else
printf("NO\n");
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
int u,v,w;
init();
for(int i=1;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
int st,ed;
scanf("%d%d",&st,&ed);
solve(n,st,ed);
return 0;
}