codeforces 652E
2016-03-26 09:20
316 查看
题目大意
给你一个nn个点,mm条边的连通图,某些边上会有宝藏,只有一个询问,问从aa到bb是否存在一条路径使得,路径上没有重边并且路径上有宝藏。范围
(1 ≤ n ≤ 3∗105,0 ≤ m ≤ 3∗105)(1 ≤ n ≤ 3*10^5, 0 ≤ m ≤ 3*10^5)思路
易得,如果一个环上有宝藏,那么我一定可以从环上的一个点进去,拿到宝藏,然后从任意一个点出来。那么我就可以缩环,建树,现在的树就是一颗某些点有宝藏,某些边有宝藏了,那我就求一下aa到bb的树上路径是否有宝藏就行了。参考代码
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define fo(i,a,b) for(int i=a;i<=b;i++) #define fd(i,a,b) for(int i=a;i>=b;i--) #define maxn 600005 #define maxsq 30 using namespace std; int n,m,S,T; int head[maxn],t[maxn * 2],vv[maxn * 2],next[maxn * 2],sum; void insert(int x,int y,int z){ t[++sum]=y; next[sum]=head[x]; vv[sum]=z; head[x]=sum; } int dfn[maxn],low[maxn],scc,cnt; int instack[maxn],sta[maxn],top,belong[maxn]; int fr[maxn],ok[maxn]; int head2[maxn],t2[2*maxn],next2[2*maxn],sum2,v2[maxn*2]; void insert2(int x,int y,int z){ t2[++sum2]=y; next2[sum2]=head2[x]; v2[sum2]=z; head2[x]=sum2; } void Tarjan(int u,int fa) { int i,v; low[u]=dfn[u]=++cnt; sta[++top]=u; instack[u]=1; for(i=head[u];i;i=next[i]) { v=t[i]; if(i==(fa^1)) continue; if(!dfn[v]) { fr[v]=i; Tarjan(v,i); low[u]=min(low[u],low[v]); } else if(instack[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { scc++; while(1) { v=sta[top--]; instack[v]=0; belong[v]=scc; if(v==u) break; } } } int fa[maxn][maxsq][2],deep[maxn]; void maketree(int x,int father){ deep[x]=deep[father]+1; for(int tmp=head2[x];tmp;tmp=next2[tmp]) { if (t2[tmp]==father) continue; fa[t2[tmp]][0][0]=x; fa[t2[tmp]][0][1]=(ok[x]) || (ok[t2[tmp]]) || (v2[tmp]); maketree(t2[tmp],x); } } bool getlca(int x,int y){ if (deep[x]<deep[y]) swap(x,y); fd(i,20,0) if (deep[fa[x][i][0]]>=deep[y]) { if (fa[x][i][1]) return 1; x=fa[x][i][0]; } if (x==y) return 0; fd(i,20,0) if (fa[x][i][0]!=fa[y][i][0]) { if (fa[x][i][1]) return 1; if (fa[y][i][1]) return 1; x=fa[x][i][0]; y=fa[y][i][0]; } if (fa[x][0][1]) return 1; if (fa[y][0][1]) return 1; return 0; } int main(){ sum=1; scanf("%d%d",&n,&m); fo(i,1,m) { int x,y,z; scanf("%d%d%d",&x,&y,&z); insert(x,y,z); insert(y,x,z); } fo(i,1,n) if (dfn[i]==0) Tarjan(i,0); fo(i,1,n) { for(int tmp=head[i];tmp;tmp=next[tmp]) { if (belong[t[tmp]]==belong[i]) { if (vv[tmp]) ok[belong[i]]=1; continue; } insert2(belong[i],belong[t[tmp]],vv[tmp]); } } maketree(1,0); fa[1][0][0]=1; fa[1][0][1]=ok[1]; fo(i,1,20) fo(j,1,scc) fa[j][i][0]=fa[fa[j][i-1][0]][i-1][0],fa[j][i][1]=fa[j][i-1][1] || fa[fa[j][i-1][0]][i-1][1]; scanf("%d%d",&S,&T); if (ok[belong[S]]||ok[belong[T]]) { puts("YES"); return 0; } if (getlca(belong[S],belong[T])) { puts("YES"); } else puts("NO"); return 0; }
相关文章推荐
- MinerConstanits.java 常量类
- 正则表达式
- 玩转微信2次开发1_交互通信api.php(微擎版)
- LightOJ 1064 Throwing Dice
- Android的adb使用
- final关键字的作用
- redis主从复制
- Android开发工具
- C++第二次作业
- Java之面向对象相关问题集
- 网络基础:IP地址分类
- awk字符串函数及其意义
- 第四周学习进度条
- android SDK 国内镜像
- C++精进篇(八)之―函数重定义、重载、重写
- awk字符串函数及其意义
- C++精进篇(七)之―操作符重载
- C++精进篇(六)之― Vector、iterator、Array
- 写给准备参加秋招的学弟学妹们~一定要来看哦~
- Delphi检查GetElementByID返回值的有效性