CodeForces - 1046B Hyperspace Highways (广义圆方树)

B. Hyperspace Highways

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

In an unspecified solar system, there are NN planets. A space government company has recently hired space contractors to build MMbidirectional Hyperspace™ highways, each connecting two different planets. The primary objective, which was to make sure that every planet can be reached from any other planet taking only Hyperspace™ highways, has been completely fulfilled. Unfortunately, lots of space contractors had friends and cousins in the Space Board of Directors of the company, so the company decided to do much more than just connecting all planets.

In order to make spending enormous amounts of space money for Hyperspace™ highways look neccessary, they decided to enforce a strict rule on the Hyperspace™ highway network: whenever there is a way to travel through some planets and return to the starting point without travelling through any planet twice, every pair of planets on the itinerary should be directly connected by a Hyperspace™ highway. In other words, the set of planets in every simple cycle induces a complete subgraph.

You are designing a Hyperspace™ navigational app, and the key technical problem you are facing is finding the minimal number of Hyperspace™ highways one needs to use to travel from planet AA to planet BB. As this problem is too easy for Bubble Cup, here is a harder task: your program needs to do it for QQ pairs of planets.

Input

The first line contains three positive integers NN (1≤N≤1000001≤N≤100000), MM (1≤M≤5000001≤M≤500000) and QQ (1≤Q≤2000001≤Q≤200000), denoting the number of planets, the number of Hyperspace™ highways, and the number of queries, respectively.

Each of the following M lines contains a highway: highway ii is given by two integers uiui and vivi (1≤ui<vi≤N1≤ui<vi≤N), meaning the planets uiui and vivi are connected by a Hyperspace™ highway. It is guaranteed that the network of planets and Hyperspace™ highways forms a simple connected graph.

Each of the following QQ lines contains a query: query jj is given by two integers ajaj and bjbj (1≤aj<bj≤N)(1≤aj<bj≤N), meaning we are interested in the minimal number of Hyperspace™ highways one needs to take to travel from planet ajaj to planet bjbj.

Output

Output QQ lines: the jj-th line of output should contain the minimal number of Hyperspace™ highways one needs to take to travel from planet ajaj to planet bjbj.

Examples

input

Copy

5 7 2
1 2
1 3
1 4
2 3
2 4
3 4
1 5
1 4
2 5

output

Copy

1
2

input

Copy

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

output

Copy

2
2
3
3

Note

The graph from the second sample:

 

题意:给你一个特殊的图,查询最短距离。

 

解题思路:根据官方题解,对原图建立广义圆方树,然后就树上路径除二就是答案。模板+1

 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=500000;
const int MAXLOGV=20;

struct edge{
    int u,v,next;
}e[MAXN*4],e1[MAXN*4];
int head1[MAXN],edge_num1;//原图
int head[MAXN],edge_num;//圆方树
void insert_edge(int u,int v){
    e1[edge_num1].u=u;
    e1[edge_num1].v=v;
    e1[edge_num1].next=head1[u];
    head1[u]=edge_num1++;
}

void insert_edge2(int u,int v){
    e[edge_num].u=u;
    e[edge_num].v=v;
    e[edge_num].next=head[u];
    head[u]=edge_num++;
}

int N,M,Q;

/****根据原图建立圆方树****/
int st[MAXN];
int low[MAXN];
int dfn[MAXN];
int n1;
void tarjan(int k,int fa)
{
    st[++st[0]]=k;
    low[k]=dfn[k]=++dfn[0];
    for(int i=head1[k];~i;i=e1[i].next)
    {
        int p=e1[i].v;
        if(p!=fa)
        {
            if(!dfn[p])
            {
                tarjan(p,k);
                if(low[p]>=dfn[k])//栈中p所在的部分与k构成了一个点双
                                  //当low[p]>dfn[k]时,这个点双只有一条边两个点。
                {
                    insert_edge2(++n1,k);
                    insert_edge2(k,n1);//新建方点n1,并向所有点双中的点连边
                    while(st[st[0]]!=p){
                        insert_edge2(n1,st[st[0]]);
                        insert_edge2(st[st[0]],n1);
                        st[st[0]--]=0;
                    }
                    insert_edge2(n1,p);
                    insert_edge2(p,n1);
                    st[st[0]--]=0;
                }
                else low[k]=min(low[k],low[p]);
            }
            else low[k]=min(low[k],dfn[p]);
        }
    }
}

/***LCA处理***/
int f[MAXLOGV+2][MAXN];
int dep[MAXN];
void dfs(int u,int fa)
{
    f[0][u]=fa;
    dep[u]=dep[fa]+1;
    for(int i=head[u];~i;i=e[i].next){
        int v=e[i].v;
        if(v==fa)
            continue;
        dfs(v,u);
    }
}
void lca_init(){
    memset(f,0,sizeof(f));
    dep[0]=0;
    dfs(1,1);
    for(int k=0;k+1<MAXLOGV;++k){
        for(int v=1;v<=n1;++v){
            f[k+1][v]=f[k][f[k][v]];
        }
    }
}
int LCA(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    for(int k=0;k<MAXLOGV;++k){
        if( (dep[v]-dep[u])>>k&1){
            v=f[k][v];
        }
    }
    if(u==v) return u;
    for(int k=MAXLOGV-1;k>=0;--k){
        if(f[k][u]!=f[k][v]){
            u=f[k][u];
            v=f[k][v];
        }
    }
    return f[0][u];
}


int main()
{
    memset(head,-1,sizeof(head));
    edge_num=0;
    memset(head1,-1,sizeof(head1));
    edge_num1=0;
    scanf("%d%d%d",&N,&M,&Q);
    n1=N;
    int u,v;
    for(int i=0;i<M;i++){
        scanf("%d%d",&u,&v);
        insert_edge(u,v);
        insert_edge(v,u);
    }
    tarjan(1,0);
    lca_init();
    while(Q--){
        scanf("%d%d",&u,&v);
        printf("%d\n",(dep[u]+dep[v]-2*dep[LCA(u,v)])/2);
    }
    return 0;
}

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值