JZOJ.5305【NOIP2017模拟8.18】C

Description

 

Input

Output

 

Sample Input

10 11
1 2
2 3
3 4
1 4
3 5
5 6
8 6
8 7
7 6
7 9
9 10 
6
1 2
3 5
6 9
9 2
9 3
9 10 

Sample Output

2
2
2
4
4
1 
 

Data Constraint

 

Hint

题意有点问题,实际上简单路径这里指的是不经过重复边的路径。

这题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 }
神奇的代码

 

posted @ 2017-08-18 18:15  ~Lanly~  阅读(178)  评论(0编辑  收藏  举报