Description
给定 (n) 个点的无向图和一个整数 (k le n),要求解决一下问题中的任何一个:求一个大小恰好为 (lceil frac n 2 ceil) 的独立集;求一个大小不超过 (k) 的环。已经可以证明对于任意给定的整数 (k) 一定可以解决这两个问题中的一个。
Solution
由于已经保证了对于任意给定的整数 (k) 一定可以解决这两个问题中的一个,我们不妨取 (k=n),此时如果原图是一棵树,那么我们直接二分图染色即可;否则,必然有一个长度不超过 (n) 的环。
考虑原问题,我们只需要找一个结点数为 (k) 的连通子图(由于原图是连通的所以我们一定能找到),对这个子图进行上面的求解即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 5005;
struct Component
{
vector <int> vec;
int c0,c1;
vector <int> vec0,vec1;
};
vector <Component> comp; // 连通分量
vector <int> g[N];
int n,m,t1,t2,t3,n1,n2,n3,vis[N],col[N],seq[N];
bool f[N][N];
vector <int> res_dfs1, res_dfs1_0, res_dfs1_1;
vector <int> ans1,ans2,ans3;
void findans(int i,int j)
{
Component &c=comp[i-1];
if(i)
{
if(j>=c.c0 && f[i-1][j-c.c0])
{
for(int i:c.vec0)
{
ans2.push_back(i);
}
for(int i:c.vec1)
{
if(ans1.size()<n1) ans1.push_back(i);
else ans3.push_back(i);
}
findans(i-1,j-c.c0);
}
else if(j>=c.c1 && f[i-1][j-c.c1])
{
for(int i:c.vec1)
{
ans2.push_back(i);
}
for(int i:c.vec0)
{
if(ans1.size()<n1) ans1.push_back(i);
else ans3.push_back(i);
}
findans(i-1,j-c.c1);
}
}
}
void dfs1(int p)
{
vis[p]=1;
if(col[p]==0) res_dfs1_0.push_back(p);
if(col[p]==1) res_dfs1_1.push_back(p);
res_dfs1.push_back(p);
for(int q:g[p])
{
if(vis[q]==0)
{
col[q]=col[p]^1;
dfs1(q);
}
else
{
if(col[p]==col[q])
{
cout<<"NO"<<endl;
exit(0);
}
}
}
}
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>n1>>n2>>n3;
for(int i=1;i<=m;i++)
{
cin>>t1>>t2;
g[t1].push_back(t2);
g[t2].push_back(t1);
}
// 分解每个连通分量
for(int i=1;i<=n;i++)
{
if(vis[i]==0)
{
res_dfs1.clear();
res_dfs1_0.clear();
res_dfs1_1.clear();
dfs1(i);
comp.push_back({res_dfs1,res_dfs1_0.size(),res_dfs1_1.size(),
res_dfs1_0,res_dfs1_1});
}
}
// 背包 DP
f[0][0]=1;
for(int i=1;i<=comp.size();i++)
{
Component &c=comp[i-1];
for(int j=c.c0;j<=n;j++) f[i][j]|=f[i-1][j-c.c0];
for(int j=c.c1;j<=n;j++) f[i][j]|=f[i-1][j-c.c1];
}
bool flagAnswer=f[comp.size()][n2];
if(flagAnswer==0)
{
cout<<"NO"<<endl;
return 0;
}
// 构造答案
findans(comp.size(),n2);
for(int i:ans1) seq[i]=1;
for(int i:ans2) seq[i]=2;
for(int i:ans3) seq[i]=3;
cout<<"YES"<<endl;
for(int i=1;i<=n;i++) cout<<seq[i];
cout<<endl;
}