• 「POI2012」约会 Rendezvous


    #2691. 「POI2012」约会 Rendezvous

    这题我简直不想说什么了,什么素质,卡常数……

    “每个顶点有且仅有一条出边”,所以是一道基环树的题,首先tarjan缩点,在缩完点后的图上求a,b的LCA,如果LCA在环内,求出a,b分别对应环中的哪一个点,显然这两个点中的一个为最优解。

    我一开始是在求LCA时顺便求出的a,b对应的点,这样使常数变大,虽然在LOJ和bzoj上都A了,但是在某OJ上疯狂T94,调了一下午+一晚上……

    这个可以提前一边dfs预处理出来:

     1 void dfs2(int x,int ci,int ff)
     2 {
     3     incir[x]=ci;
     4     for(int i=f(x);i;i=n(i))
     5     if(v(i)!=ff && belong[v(i)]!=belong[x])
     6         dfs2(v(i),ci,x);
     7 }
     8 
     9 for(int i=1;i<=tot;i++)
    10     if(scc[i].size()>1)
    11         for(int j=0;j<scc[i].size();j++)
    12             dfs2(scc[i][j],scc[i][j],d[scc[i][j]]);

    感谢ooo帮忙卡常以及mikufun大佬提醒。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #define rint register int
    #define MAXN 500010
    #define ma(x) memset(x,0,sizeof(x))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int L=1<<20|1;
    char buffer[L],*S,*T;
    #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
    using namespace std;
    struct edge
    {
        int u,v,nxt;
        #define u(x) ed[x].u
        #define v(x) ed[x].v
        #define n(x) ed[x].nxt
        #define v2(x) ed2[x].v
        #define n2(x) ed2[x].nxt
    }ed[MAXN],ed2[MAXN];
    int first[MAXN],num_e;
    #define f(x) first[x]
    int first2[MAXN],num_e2;
    #define f2(x) first2[x]
    
    int n,k;
    int d[MAXN];
    inline void add(rint u,rint v);
    inline void add2(rint u,rint v);
    inline void swap(rint *a,rint* b)
    {
        *a = *a ^ *b;
        *b = *a ^ *b;
        *a = *a ^ *b;
    }
    inline int read()
    {
        int s=0;char a=getchar();
        while(a<'0'||a>'9')a=getchar();
        while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
        return s;
    }
    int dfn[MAXN],low[MAXN],cnt;
    int stack[MAXN],top;
    bool vi[MAXN];
    int tot,belong[MAXN];
    vector<int> scc[MAXN];
    int sor[MAXN],ooo;
    int intree[MAXN],tr;
    void tarjan(int x)
    {
        dfn[x]=++cnt;low[x]=cnt;
        vi[x]=1;
        stack[++top]=x;
        for(rint i=f(x);i;i=n(i))
            if(!dfn[v(i)])tarjan(v(i)),low[x]=min(low[x],low[v(i)]);
            else if(vi[v(i)])low[x]=min(low[x],low[v(i)]);
        if(dfn[x]==low[x])
        {
            tot++;vi[x]=0;ooo=0;
            while(stack[top]!=x)
            {
                belong[stack[top]]=tot;
                scc[tot].push_back(stack[top]);
                sor[stack[top]]=++ooo;
                vi[stack[top--]]=0;
            }
            sor[stack[top]]=++ooo;
            scc[tot].push_back(stack[top]);
            belong[stack[top--]]=tot;
        }
    }
    
    int dep[MAXN],fa[MAXN][21];
    int bin[21];
    void dfs(int x,int ff,int de,int tr)
    {
        fa[x][0]=ff;dep[x]=de;intree[x]=tr;
        for(rint i=f2(x);i;i=n2(i))
            if(v2(i)!=ff && !dep[v2(i)])
                dfs(v2(i),x,de+1,tr);
    }
    int LCA(int a,int b,int x,int y,int &xi,int &yi,int &xx,int &yy)
    {
        xi=yi=0;xx=a;yy=b;
        bool pd=0;
        if(dep[x]>dep[y]){swap(x,y);swap(xx,yy);pd=1;}
        if(dep[x]!=dep[y])
        {
            while(dep[x]!=dep[y]-1)
                for(rint i=0;;i++)
                if(dep[fa[y][i]]-1<dep[x])
                {y=fa[y][i-1];yi+=bin[i-1];break;}
            yy=scc[y][0];yy=d[yy];
            y=fa[y][0],yi++;
        }
        if(x==y)
        {
            if(pd){swap(xi,yi);swap(xx,yy);}
            return y;
        }
        while(fa[x][0]!=fa[y][0])
            for(rint i=0;;i++)
            if(fa[x][i]==fa[y][i])    
            {x=fa[x][i-1],y=fa[y][i-1];xi+=bin[i-1],yi+=bin[i-1];break;}
        if(pd){swap(xi,yi);swap(x,y);}++xi,++yi;
        xx=d[scc[x][0]],yy=d[scc[y][0]];
        return fa[x][0];
    }
    int du[MAXN];
    signed main()
    {
    //    freopen("1.in","r",stdin);
    //    freopen("in.txt","r",stdin);
    
        bin[0]=1;for(rint i=1;i<20;i++)bin[i]=bin[i-1]<<1;
        n=read(),k=read();
        for(rint i=1;i<=n;i++){d[i]=read();add(d[i],i);}
        for(rint i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        for(rint i=1;i<=num_e;i++)
            if(belong[u(i)]!=belong[v(i)])
                add2(belong[u(i)],belong[v(i)]),du[belong[v(i)]]++;
        for(rint i=1;i<=tot;i++)
            if(!du[i])dfs(i,0,1,++tr);
        for(rint i=1;i<20;i++)
            for(rint j=1;j<=tot;j++)
                fa[j][i]=fa[fa[j][i-1]][i-1];
        int a,b,xi,yi,xx,yy;
        int lca,t1,t2,x1,x2,y1,y2;
        for(rint i=1;i<=k;i++)
        {
            a=read(),b=read();
            if(intree[belong[a]]!=intree[belong[b]]){puts("-1 -1");continue;}
            lca=LCA(a,b,belong[a],belong[b],xi,yi,xx,yy);
            if(!lca){puts("-1 -1");continue;}
            if(scc[lca].size()==1){printf("%d %d
    ",xi,yi);continue;}
            t1=(sor[xx]-sor[yy]+scc[belong[xx]].size()),
            t2=(sor[yy]-sor[xx]+scc[belong[xx]].size());
            if(t1>=scc[belong[xx]].size())t1-=scc[belong[xx]].size();
            if(t2>=scc[belong[xx]].size())t2-=scc[belong[xx]].size();
            swap(t1,t2);
            x1=xi,y1=yi+t2;
            x2=xi+t1,y2=yi;
            int ma1=max(x1,y1),ma2=max(x2,y2),mi1=min(x1,y1),mi2=min(x2,y2);
            if(ma1!=ma2){ma1<ma2?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
            else if(mi1!=mi2){mi1<mi2?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
            else{x1>=y1?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
        }
    }
    inline void add(rint u,rint v)
    {
        u(++num_e)=u;
        v(num_e)=v;
        n(num_e)=f(u);
        f(u)=num_e;
    }
    inline void add2(rint u,rint v)
    {
        v2(++num_e2)=v;
        n2(num_e2)=f2(u);
        f2(u)=num_e2;
    }
    疯狂T94的沙雕代码
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<cmath>
    #define rint register int
    #define MAXN 500010
    #define ma(x) memset(x,0,sizeof(x))
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    const int L=1<<20|1;
    char buffer[L],*S,*T;
    #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++)
    using namespace std;
    struct edge
    {
        int u,v,nxt;
        #define u(x) ed[x].u
        #define v(x) ed[x].v
        #define n(x) ed[x].nxt
        #define v2(x) ed2[x].v
        #define n2(x) ed2[x].nxt
    }ed[MAXN],ed2[MAXN];
    int first[MAXN],num_e;
    #define f(x) first[x]
    int first2[MAXN],num_e2;
    #define f2(x) first2[x]
    
    int n,k;
    int d[MAXN];
    inline void add(rint u,rint v);
    inline void add2(rint u,rint v);
    inline void swap(rint *a,rint* b)
    {
        *a = *a ^ *b;
        *b = *a ^ *b;
        *a = *a ^ *b;
    }
    inline int read()
    {
        int s=0;char a=getchar();
        while(a<'0'||a>'9')a=getchar();
        while(a>='0'&&a<='9'){s=s*10+a-'0';a=getchar();}
        return s;
    }
    int dfn[MAXN],low[MAXN],cnt;
    int stack[MAXN],top;
    bool vi[MAXN];
    int tot,belong[MAXN];
    vector<int> scc[MAXN];
    int sor[MAXN],ooo;
    int intree[MAXN],tr;
    int incir[MAXN],ci;
    void tarjan(int x)
    {
        dfn[x]=++cnt;low[x]=cnt;
        vi[x]=1;
        stack[++top]=x;
        for(rint i=f(x);i;i=n(i))
            if(!dfn[v(i)])tarjan(v(i)),low[x]=min(low[x],low[v(i)]);
            else if(vi[v(i)])low[x]=min(low[x],low[v(i)]);
        if(dfn[x]==low[x])
        {
            tot++;vi[x]=0;ooo=0;
            while(stack[top]!=x)
            {
                belong[stack[top]]=tot;
                scc[tot].push_back(stack[top]);
                sor[stack[top]]=++ooo;
                vi[stack[top--]]=0;
            }
            sor[stack[top]]=++ooo;
            scc[tot].push_back(stack[top]);
            belong[stack[top--]]=tot;
        }
    }
    
    int dep[MAXN],fa[MAXN][21];
    int bin[21];
    void dfs(int x,int ff,int de,int tr)
    {
        fa[x][0]=ff;dep[x]=de;intree[x]=tr;
        for(rint i=f2(x);i;i=n2(i))
            if(v2(i)!=ff && !dep[v2(i)])
                dfs(v2(i),x,de+1,tr);
    }
    void dfs2(int x,int ci,int ff)
    {
        incir[x]=ci;
        for(int i=f(x);i;i=n(i))
        if(v(i)!=ff && belong[v(i)]!=belong[x])
            dfs2(v(i),ci,x);
    }
    int LCA(int x,int y)
    {
        if(dep[x]>dep[y])swap(x,y);
            while(dep[x]!=dep[y])
                for(rint i=0;;i++)
                if(dep[fa[y][i]]<dep[x])
                {y=fa[y][i-1];break;}
        if(x==y){return y;}
        while(fa[x][0]!=fa[y][0])
            for(rint i=0;;i++)
            if(fa[x][i]==fa[y][i])    
            {x=fa[x][i-1],y=fa[y][i-1];break;}
        return fa[x][0];
    }
    int du[MAXN];
    signed main()
    {
    //    freopen("1.in","r",stdin);
    //    freopen("in.txt","r",stdin);
    
        bin[0]=1;for(rint i=1;i<20;i++)bin[i]=bin[i-1]<<1;
        n=read(),k=read();
        for(rint i=1;i<=n;i++){d[i]=read();add(d[i],i);}
        for(rint i=1;i<=n;i++)
            if(!dfn[i])tarjan(i);
        for(rint i=1;i<=num_e;i++)
            if(belong[u(i)]!=belong[v(i)])
                add2(belong[u(i)],belong[v(i)]),du[belong[v(i)]]++;
        for(rint i=1;i<=tot;i++)
            if(!du[i])dfs(i,0,1,++tr);
        for(rint i=1;i<20;i++)
            for(rint j=1;j<=tot;j++)
                fa[j][i]=fa[fa[j][i-1]][i-1];
        for(int i=1;i<=tot;i++)
        if(scc[i].size()>1)
            for(int j=0;j<scc[i].size();j++)
                dfs2(scc[i][j],scc[i][j],d[scc[i][j]]);
        int a,b,xi,yi,xx,yy;
        int lca,t1,t2,x1,x2,y1,y2;
        for(rint i=1;i<=k;i++)
        {
            a=read(),b=read();
            if(intree[belong[a]]!=intree[belong[b]]){puts("-1 -1");continue;}
            if(incir[a]==incir[b])
            {
                lca=LCA(belong[a],belong[b]);
                printf("%d %d
    ",dep[belong[a]]-dep[lca],dep[belong[b]]-dep[lca]);
                continue;
            }
            else
                xx=incir[a],yy=incir[b],xi=dep[belong[a]]-dep[belong[incir[a]]],yi=dep[belong[b]]-dep[belong[incir[b]]];
            t1=(sor[xx]-sor[yy]+scc[belong[xx]].size()),
            t2=(sor[yy]-sor[xx]+scc[belong[xx]].size());
            if(t1>=scc[belong[xx]].size())t1-=scc[belong[xx]].size();
            if(t2>=scc[belong[xx]].size())t2-=scc[belong[xx]].size();
            swap(t1,t2);
            x1=xi,y1=yi+t2;
            x2=xi+t1,y2=yi;
            int ma1=max(x1,y1),ma2=max(x2,y2),mi1=min(x1,y1),mi2=min(x2,y2);
            if(ma1!=ma2){ma1<ma2?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
            else if(mi1!=mi2){mi1<mi2?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
            else{x1>=y1?printf("%d %d
    ",x1,y1):printf("%d %d
    ",x2,y2);}
        }
    }
    inline void add(rint u,rint v)
    {
        u(++num_e)=u;
        v(num_e)=v;
        n(num_e)=f(u);
        f(u)=num_e;
    }
    inline void add2(rint u,rint v)
    {
        v2(++num_e2)=v;
        n2(num_e2)=f2(u);
        f2(u)=num_e2;
    }
    改完后的AC代码
    波澜前,面不惊。
  • 相关阅读:
    linux系统中将一列数据转换为若干列数据(列的顺序不变)
    linux系统中将矩形数据转换为一行、一列的形式
    linux系统中实现文本转置。
    linux shell 如何将多列数据变为一行数据
    linux系统中如何将一行数据变为一列
    bash: unlzma: command not found...
    linux系统中实现对行的批量替换
    linux系统中对指定行的字符串进行替换
    linux系统中对指定列的数据中的字符串进行替换
    linux系统中如何将每行特定数目字符后的字符替换为指定字符
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11172830.html
Copyright © 2020-2023  润新知