JZOJ.5305【NOIP2017模拟8.18】C
题意有点问题,实际上简单路径这里指的是不经过重复边的路径。
这题Tarjan缩点,然后LCA统计两点间环的个数k,答案就是2k个路径。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #define M 600010 6 #define N 100010 7 #define mo 100000007 8 using namespace std; 9 int head[N],next[M],to[M],n,m,belong[N],dfn[N],low[N],zhan[N],sigh[N],num,ti,q,top,deep[N],visit[N],up[N][30]; 10 long long ans,sum[N]; 11 void add(int u,int v){ 12 num++; 13 next[num]=head[u]; 14 to[num]=v; 15 head[u]=num; 16 num++; 17 next[num]=head[v]; 18 to[num]=u; 19 head[v]=num; 20 } 21 void Tarjan(int x,int fa){ 22 zhan[++top]=x; 23 ti++; 24 dfn[x]=ti; 25 low[x]=ti; 26 for (int v,i=head[x];i;i=next[i]){ 27 v=to[i]; 28 if (v==fa) continue; 29 if (!dfn[v]){ 30 Tarjan(v,x); 31 low[x]=min(low[x],low[v]); 32 } else low[x]=min(low[x],dfn[v]); 33 } 34 if (dfn[x]==low[x]){ 35 do{ sigh[x]++; 36 belong[zhan[top]]=x; 37 top--; 38 }while(zhan[top+1]!=x); 39 sigh[x]--; 40 } 41 } 42 void DFS(int x,int fa){ 43 if (x==1) up[x][0]=x; 44 else up[x][0]=fa; 45 for (int i=1;i<=25;i++) 46 up[x][i]=up[up[x][i-1]][i-1]; 47 deep[x]=deep[fa]+1; 48 if (sigh[x]) sum[x]=sum[fa]+1; 49 else sum[x]=sum[fa]; 50 for (int v,i=head[x];i;i=next[i]){ 51 v=to[i]; 52 if (belong[v]==belong[fa]) continue; 53 if (belong[v]!=belong[x]) 54 DFS(v,x); 55 } 56 } 57 long long kuai(long long a,long long b){ 58 long long ans=1; 59 long long mi=b; 60 long long qwq=a; 61 while (mi){ 62 if (mi&1) ans=ans*qwq%mo; 63 qwq=qwq*qwq%mo; 64 mi>>=1; 65 } 66 return ans; 67 } 68 int lca(int u,int v){ 69 if (deep[u]<deep[v]) swap(u,v); 70 for (int i=25;i>=0;i--) 71 if (deep[v]<=deep[up[u][i]]) 72 u=up[u][i]; 73 if (u==v) return u; 74 for (int i=25;i>=0;i--) 75 if (up[u][i]!=up[v][i]) 76 u=up[u][i],v=up[v][i]; 77 return up[u][0]; 78 } 79 int main(){ 80 scanf("%d%d",&n,&m); 81 num=0; 82 for (int i=1,u,v;i<=m;i++){ 83 scanf("%d%d",&u,&v); 84 add(u,v); 85 } 86 for (int i=1;i<=n;i++) 87 sigh[i]=0; 88 ti=0; 89 top=0; 90 Tarjan(1,0); 91 for (int i=1;i<=n;i++){ 92 if (belong[i]!=i) 93 for (int v,j=head[i];j;j=next[j]){ 94 v=to[j]; 95 if (belong[v]!=belong[i]) 96 add(v,belong[i]); 97 } 98 } 99 sum[0]=0; 100 deep[0]=0; 101 DFS(1,0); 102 scanf("%d",&q); 103 for (int i=1,u,v,father;i<=q;i++){ 104 ans=0; 105 scanf("%d%d",&u,&v); 106 if (u==v) if (sigh[belong[u]]) {printf("1\n");continue;}else {printf("0\n");continue;} 107 u=belong[u],v=belong[v]; 108 if (deep[u]<deep[v]) swap(u,v); 109 father=lca(u,v); 110 ans=sum[u]+sum[v]-2*sum[father]+(sigh[father]?1:0); 111 printf("%lld\n",kuai(2,ans)%mo); 112 } 113 return 0; 114 }