Tarjan缩环的好方法
来源:互联网 发布:借贷软件排行 编辑:程序博客网 时间:2024/06/11 23:51
我的观点
将Tarjan中的每一个最大的边双(即和其他非子边双有交集的边双)内的所有点连上一个新点,然后新点连上旧店连着的点。然后重新建树。
其他更好的方法
大家有更好的方法吗?可以通过评论或者找我讨论,谢了各位!
代码
题目求2的x到y的路径中的简单环的个数次方。(每个点最多属于一个简单环)
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define N 100005#define M 150005#define LL long long#define mo 1000000007#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[M*2];int i,j,k,l,m,n,q,en,cnt;int head[N];int u,v,w,tot,tr_tot,temp;int fa[N][18],sum[N][18];int dfn[N],low[N],stack[N],dep[N];int bel[N];LL _2[N];bool vis[M],bz[N],bz1[N];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){ dfn[x]=low[x]=++tr_tot; bz[x]=1; stack[++stack[0]]=x; int i; eg(i,x) if (!vis[edge[i].id] && edge[i].id<=m){ vis[edge[i].id]=1; if (dfn[edge[i].to]==-1){ tarjan(edge[i].to); low[x]=min(low[x],low[edge[i].to]); } else if (bz[edge[i].to]){ low[x]=min(low[x],dfn[edge[i].to]); } } if (dfn[x]==low[x]){ if (stack[stack[0]]!=x)sum[x][0]=1;else sum[x][0]=0; en=stack[0]; while (stack[stack[0]+1]!=x){ bel[stack[stack[0]]]=x; if (stack[stack[0]]!=x) bz1[stack[stack[0]]]=1; stack[0]--; } fo(i,stack[0]+2,en){ eg(j,stack[i]){ cnt++; lb(x,edge[j].to,cnt); lb(edge[j].to,x,cnt); } } }}void dfs(int x){ int i; eg(i,x) if (!bz1[edge[i].to] && fa[x][0]!=edge[i].to && x!=edge[i].to){ fa[edge[i].to][0]=x; dep[edge[i].to]=dep[x]+1; dfs(edge[i].to); }}int main(){ _2[0]=1;fo(i,1,100000) _2[i]=(_2[i-1]*2)%mo; 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)); tarjan(1); dep[1]=1; dfs(1); fo(j,1,17)fo(i,1,n){ fa[i][j]=fa[fa[i][j-1]][j-1]; 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); u=bel[u],v=bel[v]; temp=0; w=getlca(u,v); temp+=sum[w][0]; printf("%lld\n",_2[temp]); } return 0;}
阅读全文
2 0
- Tarjan缩环的好方法
- 51nod 1456 小K的技术【强连通Tarjan+缩点染色+并查集】好题~
- 好的方法
- 换行的好方法
- 解酒的好方法
- 好的人生方法
- 发外链的好方法
- 计数的好方法
- 计数的好方法
- 学习的好方法
- 【hh大神的】Tarjan + 缩点 模板
- [HAOI2006]受欢迎的牛 Tarjan缩点
- hdu 3594 强连通好题仙人掌图,对自己的tarjan模板改下用这个
- hrbust 1797 Fly【Tarjan强连通+缩点染色+最长路SPFA】好题~
- 保存网页的好方法
- 调试javascript的好方法
- 保持心情好的方法
- 治疗忧郁症的好方法
- 使用akka框架编写RPC框架
- markdown编辑器
- CSDN_Blog开通
- 手动杆
- nyoj32 组合数
- Tarjan缩环的好方法
- java单列模式---双重检校性--举哥
- 调试win系统下部署在tomcat的应用
- HDU 6188 Duizi and Shunzi(贪心+细节)
- Git基本知识与常用命令
- 上位机使用Model Bus与PLC通信实现连续地址读写
- Windows安装nodejs以及设置淘宝镜像
- 58到家数据库30条军规解读
- 【每天积累一点点】Data Binding Library官方教程翻译