zoukankan      html  css  js  c++  java
  • 洛谷2783 有机化学之神偶尔会做作弊

    题目戳这里
    一句话题意

    一个无向图,先缩掉所有的环,再询问两点直接隔了多少个点(两端也算)。

    Solution

    似乎难度称不上黑题,思路也很明显
    直接Tarjan缩点后求LCA,深度之差就是相隔的点数。
    但注意特判LCA=x或y的情况。
    本来早就可以A了,结果居然LCA打错,无语...
    可能难就难在代码比较长,有点绕,但是想清楚还是蛮好打的。
    也没什么好说的,直接看代码吧。

    Coding

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 500005;
    struct road
    {
        int to,next;
    }e[N*10];
    int head[N],cnt,be[N],to[N],num[N];
    void add(int x,int y)
    {
        cnt++;
        e[cnt].to=y;
        e[cnt].next=head[x];
        head[x]=cnt;
    }
    int sum,color[N],low[N],ins[N],tim[N],sta[N],top=1,col;
    void Tarjan(int x,int last)
    {
        tim[x]=low[x]=++sum;
        sta[top++]=x;
        ins[x]=1;
        for(int i=head[x];i!=0;i=e[i].next)
        {
          if(e[i].to!=last)
          {
            if(ins[e[i].to]==0)
            {
                Tarjan(e[i].to,x);
                low[x]=min(low[x],low[e[i].to]);
            }
            else if(ins[e[i].to]==1)
                 	low[x]=min(low[x],tim[e[i].to]);
          }
        }
        if(tim[x]==low[x])
        {
            col++;
            do
            {
                top--;
                color[sta[top]]=col;
                ins[sta[top]]=-1;
            }while(sta[top]!=x);
        }
        return ;
    }
    int n,m,news[N],fa[N],LCA[N][20],dep[N];
    road edge[N*10];
    void Readd(int x,int y)
    {
        cnt++;
        edge[cnt].to=y;
        edge[cnt].next=head[x];
        head[x]=cnt;
    }
    queue<int> q;
    bool lemon[N];
    void dfs(int x,int deep,int last)
    {
        dep[x]=deep; fa[x]=last;
        for(int i=head[x];i;i=edge[i].next)
         if(edge[i].to!=last&&dep[edge[i].to]==0) dfs(edge[i].to,deep+1,x);
    }
    int Lca(int x,int y)
    {
        if(dep[x]<dep[y]) swap(x,y);
        int popx=x,popy=y,last;
        int p=0,qu=dep[x]-dep[y];
        while(qu>0)
        {
            if(qu%2==1) x=LCA[x][p];
            qu/=2;
            p++;
        }
        if(x!=y)
        {
            for(int j=19;j>=0;j--)
              if(LCA[x][j]!=LCA[y][j]) x=LCA[x][j],y=LCA[y][j];
            last=LCA[x][0];
        }
        else last=y;
        if(popy==last) return dep[popx]-dep[last]+1;
        else return dep[popx]-dep[last]+dep[popy]-dep[last]+1;
    }
    void change(int num)
    {
        int ans[20],cl=0;
        if(num==0) {cout<<0<<endl; return ;}
        while(num>0)
        {
            ans[++cl]=num%2;
            num/=2;
        }
        for(int i=cl;i>=1;i--)
            printf("%d",ans[i]);
        cout<<endl;
    }		
    int main()
    {
        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&be[i],&to[i]);
            add(be[i],to[i]);
            add(to[i],be[i]);
        }
        for(int i=1;i<=n;i++)
            if(ins[i]==0) Tarjan(i,i);
        for(int i=1;i<=n;i++)
        	num[color[i]]++;
        memset(head,0,sizeof(head));
        cnt=0;
        for(int i=1;i<=m;i++)
            if(color[be[i]]!=color[to[i]]||(color[be[i]]==color[to[i]]&&num[color[be[i]]]==2))
            {
                Readd(color[be[i]],color[to[i]]);
                Readd(color[to[i]],color[be[i]]);
            }
        dfs(1,1,1);
        for(int i=1;i<=col;i++)
            LCA[i][0]=fa[i];
        for(int j=1;j<=19;j++)
          for(int i=1;i<=col;i++)
             LCA[i][j]=LCA[LCA[i][j-1]][j-1];
        int T;
        cin>>T;
        for(int i=1;i<=T;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            change(Lca(color[x],color[y]));
        }	
        return 0;
    }
    
  • 相关阅读:
    C#操作REDIS例子
    A C# Framework for Interprocess Synchronization and Communication
    UTF8 GBK UTF8 GB2312 之间的区别和关系
    开源项目选型问题
    Mysql命令大全——入门经典
    RAM, SDRAM ,ROM, NAND FLASH, NOR FLASH 详解(引用)
    zabbix邮件报警通过脚本来发送邮件
    centos启动提示unexpected inconsistency RUN fsck MANUALLY
    rm 或者ls 报Argument list too long
    初遇Citymaker (六)
  • 原文地址:https://www.cnblogs.com/Le-mon/p/9622306.html
Copyright © 2011-2022 走看看