• P2783 有机化学之神偶尔也会作弊


    写这篇题解仅仅是因为这是第一道没看题解,一遍过的紫题     ⁄(⁄ ⁄•⁄ω⁄•⁄ ⁄)⁄   

    题目背景

    XS中学化学竞赛组教练是一个酷爱炉石的人。

    有一天他一边搓炉石一边监考,而你作为一个信息竞赛的大神也来凑热闹。

    然而你的化竞基友却向你求助了。

    “第1354题怎么做”<--手语 他问道。

    题目描述

    你翻到那一题:给定一个烃,只含有单键(给初中生的一个理解性解释:就是一堆碳用横线连起来,横线都是单条的)。

    然后炎魔之王拉格纳罗斯用他的火焰净化了一切环(???)。所有的环状碳都变成了一个碳。如图所示。

    然后指定多组碳,求出它们之间总共有多少碳。如图所示(和上图没有关系)。

    但是因为在考试,所以你只能把这个答案用手语告诉你的基友。你决定用二进制来表示最后的答案。如图所示(不要在意,和题目没有什么没关系)。

    输入格式

    第一行两个整数n,m.表示有n个点,m根键

    接下来m行每行两个整数u,v表示u号碳和v号碳有一根键

    接下来一个整数tot表示询问次数

    接下来tot行每行两个整数,a,b表示询问的两个碳的编号

    输出格式

    共tot行

    每行一个二进制数

    输入输出样例

    输入 #1
    3 2
    1 2
    2 3
    2
    1 2
    2 3
    
    输出 #1
    10
    10

    说明/提示

    1<n<=10000,1<m<=50000

    #(两个碳不成环)

    -------------------------------------------------------小分割线-----------------------------------------------------------

    一看到题目,找环,Tarjan

    但是是无向边,所以普通的tarjan肯定是行不通

    所以我们要加一个限定条件:

    if(edge[i].to==father[now])continue;

    防止它直接回到父节点

    好,只要这个对了,应该都做出来了吧

    接下来就是求LCA,以任意一个点作为根节点

    dis[i]表示到根节点的距离,很显然,两个碳之间的数量就是:

    dis[x]+dis[y]-dis[lca(x,y)]+1

    一下就是代码(看起来很长,只不过是我最近不知道为什么喜欢打树剖,倍增求lca代码就短很多)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define cg ch=getchar()
    
    const int _=50002*2;
    int number,edge_n,number_w,root,cnt,dis[_];
    int father[_],size[_],son[_],id[_],top[_],deep[_];
    int color[_],sum,q[_],hd,dfn[_],low[_],deeth,res[_];
    int ver[_],nxt[_],head[_],tot,cx[_],cy[_];
    
    int read(){
        int s=0,w=1;char cg;
        while(ch<'0'||ch>'9')w=(ch=='-')?-1:1,cg;
        while(ch>='0'&&ch<='9')s=s*10+ch-'0',cg;
        return s*w;
    }
    
    void add(int x,int y){
        ver[++tot]=y;nxt[tot]=head[x];head[x]=tot;
    }
    
    void Tarjan(int now,int fa){
        low[now]=dfn[now]=++deeth;res[now]=1;
        q[++hd]=now;
        for(int i=head[now];i;i=nxt[i]){
            int y=ver[i];
            if(y==fa)continue;
            if(!dfn[y])Tarjan(y,now),low[now]=min(low[y],low[now]);
            else if(res[y])low[now]=min(low[now],dfn[y]);
        }
        if(dfn[now]==low[now]){
            color[now]=++sum;res[now]=0;
            while(q[hd]!=now){
                color[q[hd]]=sum;res[q[hd--]]=0;
            }
            hd--;
        }
    }
    
    void dfs1(int now,int fa,int de){
        deep[now]=de;father[now]=fa;size[now]=1;id[++cnt]=now;dis[now]=dis[fa]+1;
        int maxx=-1;
        for(int i=head[now];i;i=nxt[i]){
            int y=ver[i];
            if(y==fa)continue;
            dfs1(y,now,de+1);
            size[now]+=size[y];
            if(size[y]>maxx)maxx=size[y],son[now]=y;
        }
    }
    
    void dfs2(int now,int topf){
        top[now]=topf;
        if(!son[now])return;
        dfs2(son[now],topf);
        for(int i=head[now];i;i=nxt[i]){
            int y=ver[i];
            if(y==son[now]||y==father[now])continue;
            dfs2(y,y);
        }
    }
    
    int get_LCA(int x,int y){
        while(top[x]!=top[y]){
            if(deep[top[x]]<deep[top[y]])swap(x,y);
            x=father[top[x]];
        }
        if(deep[x]>deep[y])swap(x,y);
        return x;
    }
    
    void turn(int now){
        int a[_]={0},tt=0;
        while(now>0){
            a[++tt]=now%2;now/=2;
        }
        for(int i=tt;i>=1;i--)cout<<a[i];
        cout<<endl;
    }
    
    signed main(){
        number=read();edge_n=read();root=1;
        for(int i=1;i<=edge_n;i++){
            cx[i]=read(),cy[i]=read();
            add(cx[i],cy[i]);add(cy[i],cx[i]);
        }
        for(int i=1;i<=number;i++)
           if(!dfn[i])Tarjan(i,0);
        memset(head,0,sizeof(head));memset(nxt,0,sizeof(nxt));
        memset(ver,0,sizeof(ver));tot=0;
        for(int i=1;i<=edge_n;i++){
            if(color[cx[i]]!=color[cy[i]])
              add(color[cx[i]],color[cy[i]]),add(color[cy[i]],color[cx[i]]);
        }
        dfs1(root,0,0);dfs2(root,root);
        number_w=read();
        for(int i=1;i<=number_w;i++){
            int x=read(),y=read(),lca=get_LCA(color[x],color[y]);
    //        cout<<color[x]<<" "<<color[y]<<" "<<lca<<" : ";
            turn(dis[color[x]]+dis[color[y]]-2*dis[lca]+1);
        }
        return 0;
    }
  • 相关阅读:
    pyVmomi入门
    一个简单的web框架实现
    H3C交换配置PBR最佳实践
    jQuery入门第三
    jQuery入门第二
    JS笔记 入门第四
    JS笔记 入门第三
    JS笔记 入门第二
    day16
    python之路-DAY10
  • 原文地址:https://www.cnblogs.com/GMSD/p/11733018.html
Copyright © 2020-2023  润新知