D. Strange Housing 题解(思维+染色)
题目链接
题目大意
这个题意好绕
就是一个\(n\)个点 \(m\)条双向边的图
你要对一些点进行标记,并且标记的点不能直接相邻
如果两个相邻的点都没有被标记,那么这两个点的边则被删除
看最后能否构成一个连通图
题目思路
就是如果题目不连通那就是NO,否则就是YES
染色方案就是类似于bfs层层染色
保证不能相邻的点都被标记
代码
#include<bits/stdc++.h>
#define fi first
#define se second
#define debug cout<<"I AM HERE"<<endl;
using namespace std;
typedef long long ll;
const int maxn=1e6+5,inf=0x3f3f3f3f,mod=1e9+7;
const double eps=1e-6;
int n,m;
vector<int> g[maxn];
vector<int> ans;
int vis[maxn];
signed main(){
int _;cin>>_;
while(_--){
cin>>n>>m;
ans.clear();
for(int i=1;i<=n;i++){
vis[i]=0;
g[i].clear();
}
for(int i=1,u,v;i<=m;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
queue<int> que;
que.push(1);
vis[1]=1;
ans.push_back(1);
// 0没有染色
// 1黑色
// 2白色
while(!que.empty()){
int x=que.front();
que.pop();
for(auto u:g[x]){
if(vis[u]) continue;
if(vis[x]==1){
vis[u]=2;
}else{
bool flag=1;
for(auto v:g[u]){
flag=(flag&(vis[v]!=1));
}
if(flag){
vis[u]=1;
ans.push_back(u);
}else{
vis[u]=2;
}
}
que.push(u);
}
}
for(int i=1;i<=n;i++){
if(vis[i]==0){
printf("NO\n");
break;
}
if(i==n){
printf("YES\n");
printf("%d\n",ans.size());
for(auto x:ans){
printf("%d ",x);
}
printf("\n");
}
}
}
return 0;
}
不摆烂了,写题