图论 —— 弦图 —— LexBFS 算法

【概述】

LexBFS 是字典序广度优先搜索(Lexicographic BFS),其常用于弦图的判定。

每次按从 n 到 1 的顺序依次给点编号,每个点维护一个 list,用于记录与其相邻的已标号点的标号,每次选择 list 中字典序最大的未标号点标号。

LexBFS 与 BFS 的不同,在于每次扩展的结点加了特殊的顺序

检查时利用桶排的思想,在更新一个点的 list 时,新建一个桶,且任何时候桶的数目不超过 n,通过维护桶中元素来进行判定

【实现】

struct Edge{
    int to;
    Edge(){}
    Edge(int to):to(to){}
};
struct Node{
    int id,num;
    Node(){}
    Node(int id,int num):id(id),num(num){}
    friend bool operator<(Node a,Node b) {
        return a.num<b.num;
    }
};
int n,m;
int G[N][N];
vector<Edge>edge[N];
int link[N],tot;//标号序列
int order[N];//完美消除序列
int num[N];//点编号
int bucket[N];//更新一个点的标号序列时的桶
bool vis[N];

void bfs(int x){//维护标号序列
    memset(num,0,sizeof(num));
    memset(link,0,sizeof(link));
    memset(vis,0,sizeof(vis));
    tot=n;

    priority_queue<Node> Q;
    Q.push(Node(x,1));
    while(!Q.empty()) {
        Node now=Q.top();
        Q.pop();
        if(!vis[now.id]){
            vis[now.id]=true;
            link[tot]=now.id;
            order[now.id]=tot;
            tot--;
            if(tot==0)
                break;
        }
        for(int i=0;i<edge[now.id].size();i++) {
            int to=edge[now.id][i].to;
            num[to]++;
            if(!vis[to])
               Q.push(Node(to,num[to]));
        }
    }
}
bool check() {
    bfs(1);//维护标号序列

    for(int i=1;i<=n;i++){
        int minn=n+1;
        int tail=0;//桶的指针
        int value;
        for(int j=0;j<edge[link[i]].size();j++) {
            int to=edge[link[i]][j].to;
            if(order[to]>i) {
                if(minn>order[to]) {
                    minn=order[to];
                    value=to;
                }
                bucket[tail++]=to;//入桶
            }
        }
        for(int j=0;j<tail;j++) {
            if(bucket[j]!=value&&G[value][bucket[j]]==0)
                return false;
        }
    }
    return true;
}
int main() {
    scanf("%d%d",&n,&m);

    memset(G,0,sizeof(G));
    for(int i=0;i<m;i++){
        int x,y;
        scanf("%d%d",&x,&y);
        edge[x].push_back(y);
        edge[y].push_back(x);
        G[x][y]=1;
        G[y][x]=1;
    }
    if(check())
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值