Codeforces 231E

各种模板。。。

边双联通分量+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]);
}


你可能感兴趣的:(struct,query)