zoukankan      html  css  js  c++  java
  • 【NOIP模拟】夕阳

    “我有个愿望,我希望在灿烂千阳时遇见你。”

    是啊,我也希望。

    题面

    这是个有n个点的世界,有m条无向边连接着这n个点,但是不保证点之间能够互相到达。

    “这个世界的夕阳,只在奇数长的简单路径的尽头。”一个神如是说。

    于是我想知道对于一个点对(x,y),x到y之间的所有简单路径中是否存在长度为奇数的路径,只有这样,我才能找到存在有夕阳的路。

    对于50%的数据,1≤n,m,q≤500

    对于100%的数据,,1≤n,q,m≤100000

    分析

    比较困难的是到底怎么判这个奇边呢?

    多画图,会发现,u和v之间有奇边无非两种情况。

    1.dis{u,v}&1==0

    2.dis{u,v}&1==1,但是u和v的路径上,有一条边在一个奇环内。意思是,如果一个奇环边数是5,本来u,v之间的距离是4,可以从奇环绕着走,距离变为4-1+5-1=7。

    所以,在计算点双联通分量的同时,一旦遇到了返祖边,就判断此环是否是奇环,如果是,退栈的过程中将这个环的所有点都标记上。

    最后用lca可求两点距离,用于判断情况1。同时我们维护了每个点在多少个奇环内,也可以通过lca的奇环数量与u,v两点的奇环数量,判断u,v是否有边在奇环内。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define N 100100
    int n,m,op,ans,cnt,gro,tot,top,tim;
    int fa[N][20],first[N],col[N],dfn[N],low[N];
    int s[N],sta[N],ins[N],odd[N],dep[N];
    struct email
    {
        int u,v;
        int nxt;
    }e[N*4];
    queue<int>q;
    inline void add(int u,int v)
    {
        e[++cnt].nxt=first[u];first[u]=cnt;
        e[cnt].u=u;e[cnt].v=v;
    }
    inline void read(int &x)
    {
        x=0;int fh=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        x*=fh;
    }
    
    
    void tarjan(int u,int pre)
    {
        dfn[u]=low[u]=++tot;
        sta[++top]=u;ins[u]=1;
        for(int i=1;i<=tim;i++)
            fa[u][i]=fa[fa[u][i-1]][i-1];
        for(int i=first[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(v==pre)continue;
            if(!dfn[v])
            {    
                fa[v][0]=u;
                dep[v]=dep[u]+1;
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
            }
            else
                if(ins[v])
                {
                    low[u]=min(low[u],dfn[v]);
                    if(dep[u]%2==dep[v]%2)odd[u]=1;
                }
        }
        ins[u]=0;
        if(dfn[u]==low[u])
        {
            int pos=top,w=0;
            while(sta[pos]!=u)w|=odd[sta[pos--]];
            if(w)
            {
                for(int i=pos+1;i<=top;i++)    
                    s[sta[i]]++;
            }
            gro++;
            for(int i=pos;i<=top;i++)
                col[sta[i]]=gro,ins[sta[i]]=0;
            top=pos-1;
        }
    }
    
    inline int lca(int x,int y)
    {
        if(dep[x]<dep[y])
            swap(x,y);
        int t=dep[x]-dep[y];
        for(int i=0;(1<<i)<=t;i++)
            if(t&(1<<i))
                x=fa[x][i];
        if(x==y)return x;
        for(int i=19;i>=0;i--)
            if(fa[x][i]!=fa[y][i])
                x=fa[x][i],y=fa[y][i];
        return fa[x][0];
    }
    
    
    void dfs(int u)
    {
        for(int i=first[u];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if(fa[v][0]==u)    
            {
                s[v]+=s[u];
                dfs(v);
            }
        }
    }
    
    
    int main()
    {
        read(n);read(m);
        for(int i=1;i<=m;i++)
        {
            int u,v;
            read(u);read(v);
            add(u,v);add(v,u);
        }
        tim=log(n)/log(2)+1;
        for(int i=1;i<=n;i++)
            if(!col[i])
            {
                dep[i]=1;
                fa[i][0]=i;
                tarjan(i,i);
            }    
        for(int i=1;i<=n;i++)
            if(fa[i][0]==i)
                dfs(i);
        read(op);
        for(int i=1;i<=op;i++)
        {
            int u,v;
            read(u);read(v);
            if(fa[u][tim]!=fa[v][tim])
                printf("No
    ");
            else
            {
                int pref=lca(u,v);
                if ((dep[u]+dep[v]-dep[pref]*2)%2==1||s[u]+s[v]-s[pref]*2>0)
                    printf("Yes
    ");
                else printf("No
    ");
            }    
        }
        return 0;
        
    }

    送一组考场上造的小样例

    input
    23 22
    1 2
    1 3
    3 9
    8 9
    2 4
    4 5
    5 8
    5 6
    5 7
    10 11
    11 12
    14 15
    15 16
    16 17
    14 17
    18 19
    18 20
    19 20
    20 21
    20 22
    21 23
    22 23
    11
    10 20 
    12 8 
    2 4 
    7 9 
    1 5 
    1 7 
    13 13 
    1 1 
    20 19 
    14 18 
    4 9 
    
    output
    No
    No
    Yes
    Yes
    Yes
    Yes
    No
    No
    Yes
    No
    Yes
    “Make my parents proud,and impress the girl I like.”
  • 相关阅读:
    MSSQL-sql server-视图简介
    MSSQL 如何采用sql语句 获取建表字段说明、字段备注、字段类型、字段长度
    mssql instead of 触发器应用一-创建只读视图(view)的方法
    DVWA-XSS学习笔记
    DVWA-命令执行学习笔记
    DVWA-暴力破解学习笔记
    kali权限提升之本地提权
    信息收集之主动信息收集(二)
    kali权限提升之配置不当提权与WCE
    linux 搭建squid代理服务器
  • 原文地址:https://www.cnblogs.com/NSD-email0820/p/9799050.html
Copyright © 2011-2022 走看看