社区讨论

T 了两个点,不知道是算法问题还是常数问题

P2783有机化学之神偶尔会做作弊参与者 3已保存回复 5

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
5 条
当前快照
1 份
快照标识符
@lo2ac37e
此快照首次捕获于
2023/10/23 10:35
2 年前
此快照最后确认于
2023/11/03 10:47
2 年前
查看原帖
望指教。
tarjan 缩点染色,建新图(lyd书的方式),最后跑 lca
CPP
#include <cstdio>
#include <cmath>
#include <algorithm>
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
using namespace std;

const int maxn=1e4+3;
const int maxm=1e5+3;
// Edge_number in a general graph is twice that of a one-way graph
struct Edge{int v,next;};
Edge edge[maxm],edge2[maxm];
int head[maxn],dfn[maxn],low[maxn],stac[maxn],color[maxn],fa[maxn];
int n,m,tot,num,top,cnt,tot_in_txt,lcafa[maxn][25];
int head2[maxn],tot2,dep[maxn],max0;
bool ins[maxn];

const int topow[] = {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192};

inline void rd(int &x){
	int w=x=0;
	char ch=0;
	while(ch<'0'||'9'<ch) w|=(ch=='-'),ch=getchar();
	while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
	x=w?-x:x;
}

inline void addedge(int x,int y){
    edge[++tot].v=y;
    edge[tot].next=head[x];
    head[x]=tot;
}

inline void addedge2(int x,int y){
    edge2[++tot2].v=y;
    edge2[tot2].next=head2[x];
    head2[x]=tot2;
}

void tarjan(int x){
    low[x]=dfn[x]=++num;
    stac[++top]=x; ins[x]=true;
    for(int i=head[x];i;i=edge[i].next){
        int y=edge[i].v;
        if(!dfn[y]){
            fa[y]=x;
            tarjan(y);
            low[x]=MIN(low[x],low[y]);
        }
        else if(ins[y] && y!=fa[x]){
            low[x]=MIN(low[x],dfn[y]);
        }
    }
    if(dfn[x]==low[x]){
        ++cnt; int y;
        do{
            y=stac[top--]; ins[y]=false;
            color[y]=cnt;
        }while(x!=y);
    }
}

void lcainit(int x){
    for(int i=1;i<=max0;i++)
        if(lcafa[x][i-1])lcafa[x][i]=lcafa[lcafa[x][i-1]][i-1];
        else break;
    for(int i=head2[x];i;i=edge2[i].next){
        int y=edge2[i].v;
        if(y!=lcafa[x][0]){
            lcafa[y][0]=x;
            dep[y]=dep[x]+1;
            lcainit(y);
        }
    }
}

inline int lca(int u,int v){
    if(dep[u]<dep[v])swap(u,v);
    int delta=dep[u]-dep[v];
    for(int x=0;x<=max0;x++)
        if((1<<x)&delta)u=lcafa[u][x];
    if(u==v)return u;
    for(int x=max0;x>=0;x--)
        if(lcafa[u][x]!=lcafa[v][x]){
            u=lcafa[u][x];
            v=lcafa[v][x];
        }
    return lcafa[u][0];
}

int main(){
    rd(n); rd(m);
    for(int i=1;i<=m;i++){
        int x,y;
        rd(x); rd(y);
        addedge(x,y);
        addedge(y,x);
    }
    rd(tot_in_txt);
    
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i);
    }

    for(int x=1;x<=n;x++){
        for(int i=head[x];i;i=edge[i].next){
            int y=edge[i].v;
            if(color[x]!=color[y]){
                addedge2(color[x], color[y]);
                addedge2(color[y], color[x]);
            }
        }
    }
    
    max0=(int)(log(cnt)/log(2))+3;
    lcainit(1);

    while(tot_in_txt--){
        int a,b;
        rd(a); rd(b);
        int k = lca(color[a], color[b]);
        int temp = dep[color[a]] + dep[color[b]] - (dep[k]<<1) + 1;

        char ans[15] = "00000000000000";
        for(int i=13; ~i; i--){
            if(temp>=topow[i]){
                ans[13-i] = '1';
                temp -= topow[i];
            }
        }
        int i = 0;
        while(ans[i]=='0') i++;
        for(; i<=13; i++)putchar(ans[i]);
        putchar('\n');
    }

    return 0;
}

回复

5 条回复,欢迎继续交流。

正在加载回复...