题意:有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; }