4847. 【NOIP2016提高A组集训第5场11.2】夕阳
2017-09-01 17:11
232 查看
题目大意
有n个点的图,有m条无向边连接着这n个点,但是不保证点之间能够互相到达。对于一个点对(x,y),x到y之间的所有简单路径中是否存在长度为奇数的路径。
题解
简单环:不经过重复点。边双连通图:不存在桥的图。
边双连通分量:边双连通图中的任意一子图。
对于一个简单奇环中任意两个点,这两个点的距离可奇可偶。
对于包含这个简单奇环的边双,其中的任意两点的距离可奇可偶。
所以用Tarjan求出奇环就行了。
最后缩成一棵树,求一下x到y的路径有没有奇环就行了。
或者x到y的路径长度就是奇数。
其实没必要缩成一棵树。
因为在对dfs树判环的时候,环中最深的点打个Tag,然后倍增求x到y中有几个奇环就OK了。
代码
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #define N 150005 #define fo(i,a,b) for(i=a;i<=b;i++) #define fd(i,a,b) for(i=a;i>=b;i--) #define eg(i,x) for(i=head[x];i;i=edge[i].next) using namespace std; struct note{ int to,next,id; };note edge[N*2]; int i,j,k,l,n,m,q,BEL,temp; int u,v,w,tot,tr_tot,en; int head ; int dfn ,dep ,low ; int belong ,bel ,sum [18]; int stack ,fa [18]; bool pp,scir ,vis ,isc ; bool instack ; void lb(int x,int y,int z){edge[++tot].to=y;edge[tot].next=head[x];edge[tot].id=z;head[x]=tot;} int getlca(int x,int y){ if (dep[x]<dep[y]) swap(x,y); int i; fd(i,17,0)if(dep[fa[x][i]]>=dep[y])temp+=sum[x][i],x=fa[x][i]; if (x==y) return x; fd(i,17,0) if (fa[x][i]!=fa[y][i]){ temp+=sum[x][i]+sum[y][i]; x=fa[x][i],y=fa[y][i]; } if (x!=y) temp+=sum[x][0]+sum[y][0]; return fa[x][0]; } void tarjan(int x,int id){ int i; dfn[x]=low[x]=++tr_tot; stack[++stack[0]]=x; instack[x]=1; bel[x]=BEL; eg(i,x) if (!vis[edge[i].id]){ vis[edge[i].id]=1; if (dfn[edge[i].to]==-1){ dep[edge[i].to]=dep[x]+1; fa[edge[i].to][0]=x; tarjan(edge[i].to,edge[i].id); low[x]=min(low[x],low[edge[i].to]); } else if (instack[edge[i].to]){ if ((dep[x]-dep[edge[i].to])%2==0)sum[x][0]++; low[x]=min(low[x],dfn[edge[i].to]); } } if (dfn[x]==low[x]){ temp=0;en=stack[0]; if (stack[stack[0]]==x) pp=0;else pp=1; while (stack[stack[0]+1]!=x){ temp=max(temp,sum[stack[stack[0]]][0]); belong[stack[stack[0]]]=x; instack[stack[stack[0]]]=0; stack[0]--; } if (temp) fo(i,stack[0]+1,en) sum[stack[i]][0]++; } } int main(){ freopen("sunset.in","r",stdin); freopen("sunset.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,m){ scanf("%d%d",&u,&v); lb(u,v,i);lb(v,u,i); } memset(dfn,255,sizeof(dfn)); memset(low,255,sizeof(low)); fo(i,1,n) if (dfn[i]==-1){ BEL=i; dep[i]=1; tarjan(i,0); } fo(j,1,17)fo(i,1,n){ fa[i][j]=fa[fa[i][j-1]][j-1]; if(fa[i][j])sum[i][j]=sum[fa[i][j-1]][j-1]+sum[i][j-1]; } scanf("%d",&q); fo(i,1,q){ scanf("%d%d",&u,&v); if (bel[u]!=bel[v]){ printf("No\n"); continue; } temp=0; w=getlca(u,v); if (temp>0) printf("Yes\n");else if ((dep[u]+dep[v]-dep[w]*2)%2==1)printf("Yes\n");else printf("No\n"); } return 0; }
相关文章推荐
- 【JZOJ4847】【NOIP2016提高A组集训第5场11.2】夕阳
- 【NOIP2016提高A组集训第5场11.2】夕阳
- JZOJ4847【NOIP2016提高A组集训第5场11.2】夕阳
- JZOJ 4845 【NOIP2016提高A组集训第5场11.2】寻找
- JZOJ4846【NOIP2016提高A组集训第5场11.2】行走
- 4845. 【NOIP2016提高A组集训第5场11.2】寻找
- 【JZOJ4845】【NOIP2016提高A组集训第5场11.2】寻找
- 【JZOJ4846】【NOIP2016提高A组集训第5场11.2】行走
- 【NOIP2016提高A组集训第5场11.2】寻找
- 【NOIP2016提高A组集训第5场11.2】行走
- JZOJ4823. 【NOIP2016提高A组集训第1场10.29】小W学物理
- JZOJ4861【NOIP2016提高A组集训第7场11.4】推冰块
- 【NOIP2016提高A组集训第8场11.5】心理学概论
- 【JZOJ4868】【NOIP2016提高A组集训第9场11.7】Simple
- JZOJ 4826. 【NOIP2016提高A组集训第2场10.30】小澳的葫芦
- 【JZOJ4877】【NOIP2016提高A组集训第10场11.8】力场护盾
- 【JZOJ4889】【NOIP2016提高A组集训第14场11.12】最长公共回文子序列
- JZOJ4893【NOIP2016提高A组集训第15场11.14】过河
- 4888. 【NOIP2016提高A组集训第14场11.12】最近公共祖先 (2017.10B组)
- 【JZOJ4832】【NOIP2016提高A组集训第3场10.31】高维宇宙