51nod 2879 Pursuit For Artifacts 邊雙連通分量+縮點
阿新 • • 發佈:2020-09-06
題解:問a,b之間是否有z=1的邊,其實就是找一下邊雙連通分量,縮點後重新建圖,變成了一棵樹,詢問a,b之間的邊權和是否>0。
可以直接從a開始spfa找一下最長路,看看是否有dis[b]>0
#include<cstdio> #include<vector> #include<queue> using namespace std; const int N=3e5+10; int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,m; int head[N],pos; struct edge{ int fr,to,next,w; }e[N<<1],E[N<<1]; void add(int x,int y,int z) { e[++pos].next=head[x]; e[pos].fr=x; e[pos].to=y; e[pos].w=z; head[x]=pos; } int head1[N],ppos; void add1(int x,int y,int z) { E[++ppos].next=head1[x]; E[ppos].fr=x; E[ppos].to=y; E[ppos].w=z; head1[x]=ppos; } int dfn[N],low[N],st[N],top,cnt,bel[N],bcc,ins[N]; void tarjan(int u,int f) { dfn[u]=low[u]=++cnt; st[++top]=u;//ins[u]=1; for(int i=head[u];i;i=e[i].next) { int v=e[i].to;if(v==f)continue; if(!dfn[v]) { tarjan(v,u); low[u]=min(low[u],low[v]); } else low[u]=min(low[u],dfn[v]); } if(low[u]==dfn[u]) { bcc++; while(st[top]!=u) { //ins[st[top]]=0; bel[st[top--]]=bcc; } //ins[st[top]]=0; bel[st[top--]]=bcc; } } int w[N]; void build() { for(int i=1;i<=pos;i+=2) { int fr=e[i].fr,to=e[i].to; if(bel[fr]==bel[to]&&e[i].w==1) w[bel[fr]]=1; else if(bel[fr]!=bel[to]) add1(bel[fr],bel[to],e[i].w),add1(bel[to],bel[fr],e[i].w); } } queue<int> q; int vis[N],dis[N]; int query(int x,int y) { q.push(x);vis[x]=1;dis[x]=w[x]; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head1[u];i;i=E[i].next) { int v=E[i].to;if(vis[v])continue; if(dis[v]<dis[u]+E[i].w+w[v]) dis[v]=dis[u]+E[i].w+w[v]; q.push(v);vis[v]=1; } } return dis[y]; } int main() { n=read(),m=read(); for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); add(x,y,z);add(y,x,z); } for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i,0); build(); int a,b; scanf("%d%d",&a,&b); if(query(bel[a],bel[b])!=0) puts("YES");else puts("NO"); return 0; }