各种模板。。。
边双联通分量+LCA
#include<cstring> #include<cstdio> #include<stack> #include<algorithm> #define mod 1000000007 #define N 100100 using namespace std; typedef long long ll; int head1[N],head2[N],head3[N],cnt; int scc,depth,dfn[N],low[N],belong[N]; int ok[N],sum[N]; stack<int>sta; struct Edge{ int v,next; }edge[N*4]; int f[N],flag[N]; ll ans[N]; struct Query{ int v,id,next; }query[N*2]; void addedge(int u,int v,int *head){ edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; edge[cnt].v=u; edge[cnt].next=head[v]; head[v]=cnt++; } void addedge1(int u,int v,int id){ query[cnt].v=v; query[cnt].id=id; query[cnt].next=head3[u]; head3[u]=cnt++; query[cnt].v=u; query[cnt].id=id; query[cnt].next=head3[v]; head3[v]=cnt++; } void init(){ memset(head1,-1,sizeof(head1)); memset(head2,-1,sizeof(head2)); memset(head3,-1,sizeof(head3)); memset(dfn,0,sizeof(dfn)); memset(ok,0,sizeof(ok)); memset(sum,0,sizeof(sum)); memset(f,0,sizeof(f)); memset(flag,0,sizeof(flag)); cnt=depth=scc=0; } void tarjan(int u,int fa){ int i; dfn[u]=low[u]=++depth; sta.push(u); for(i=head1[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa)continue; if(dfn[v]==0){ tarjan(v,u); low[u]=min(low[u],low[v]); } else low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ scc++; int cou=0; while(1){ int tem=sta.top(); sta.pop(); belong[tem]=scc; cou++; if(tem==u)break; } if(cou>1)ok[scc]=1; } } void dfs(int u,int fa){ int i; sum[u]=sum[fa]+ok[u]; for(i=head2[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa)continue; dfs(v,u); } } int find(int u){ if(f[u]==u)return u; return f[u]=find(f[u]); } ll quick(int num){ ll summ=1,zi=2; while(num){ if(num%2) summ=(summ*zi)%mod; zi=(zi*zi)%mod; num/=2; } return summ; } void Tarjan(int u,int fa){ int i; f[u]=u; for(i=head2[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v!=fa){ Tarjan(v,u); f[v]=u; } } flag[u]=1; for(i=head3[u];i!=-1;i=query[i].next){ int v=query[i].v; if(flag[v]){ int t=find(v); ans[query[i].id]=quick(sum[u]+sum[v]-2*sum[t]+ok[t]); } } } int main(){ int k,i,n,m; int u,v; scanf("%d %d",&n,&m); init(); for(i=1;i<=m;i++){ scanf("%d %d",&u,&v); addedge(u,v,head1); } for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); int last=cnt; //这里注意一下 for(i=0;i<last;i+=2) //建新图 if(belong[edge[i].v]!=belong[edge[i+1].v]) addedge(belong[edge[i].v],belong[edge[i+1].v],head2); dfs(1,0); scanf("%d",&k); cnt=0; //这里注意一下 for(i=1;i<=k;i++){ scanf("%d %d",&u,&v); addedge1(belong[u],belong[v],i); } Tarjan(1,0); for(i=1;i<=k;i++) printf("%I64d\n",ans[i]); }