【概述】
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;
}