「杂题乱刷2」CF1354E
题目链接
CF1354E Graph Coloring (*2100)
解题思路
发现这个东西就是类似于二分图染色的东西。
因为 \(2\) 只能和 \(1,3\) 链接。其余种类的点都不能连接。
不妨把 \(1,3\) 都看成同一个点放到最后处理。
那么我们就相当于是要找到一种方案使得选择每个联通快的黑点或白点,使得最终选择的总节点个数为颜色 \(2\) 的个数。
这个问题可以轻松用背包来解决。
参考代码
#include<bits/stdc++.h>
using namespace std;
//#define map unordered_map
#define re register
#define ll long long
#define forl(i,a,b) for(re ll (i)=(a);i<=(b);(i)++)
#define forr(i,a,b) for(re ll (i)=(a);i>=(b);(i)--)
#define pii pair<ll,ll>
#define mid ((l+r)>>1)
#define lowbit(x) (x&-x)
#define pb push_back
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
#define endl '\n'
#define QwQ return 0;
#define cfy cout<<"YES\n";
#define cfn cout<<"NO\n";
ll _t_;
void _clear(){}
ll n,m;
ll k1,k2,k3;
vector<ll>G[5010];
ll col[5010];
ll x,y;
ll k;
ll a[5010],b[5010];
vector<ll>A[5010],B[5010];
ll dp[5010][5010];
ll ans[5010];
void dfs(ll x,ll fa,ll y)
{
if(y==1)
a[k]++,
A[k].pb(x);
else
b[k]++,
B[k].pb(x);
col[x]=y;
for(auto i:G[x])
if(i!=fa)
{
if(!col[i])
dfs(i,x,3^y);
else if((3^y)!=col[i])
{
cfn;
exit(0);
}
}
}
void solve()
{
_clear();
cin>>n>>m>>k1>>k2>>k3;
forl(i,1,m)
cin>>x>>y,
G[x].pb(y),
G[y].pb(x);
forl(i,1,n)
if(!col[i])
k++,
dfs(i,0,1);
dp[0][0]=1;
forl(i,1,k)
{
forr(j,k2,a[i])
dp[i][j]|=dp[i-1][j-a[i]];
forr(j,k2,b[i])
dp[i][j]|=dp[i-1][j-b[i]];
}
if(dp[k][k2])
{
cfy;
forl(i,1,n)
ans[i]=1;
forr(i,k,1)
{
if(k2-a[i]>=0 && dp[i-1][k2-a[i]])
{
k2-=a[i];
for(auto j:A[i])
ans[j]=2;
}
else if(k2-b[i]>=0 && dp[i-1][k2-b[i]])
{
k2-=b[i];
for(auto j:B[i])
ans[j]=2;
}
else if(dp[i-1][k2])
continue;
else
exit(-1);
}
if(k2>0)
exit(-1);
ll num=0;
forl(i,1,n)
{
if(ans[i]==2)
cout<<2;
else
{
num++;
if(num<=k1)
cout<<1;
else
cout<<3;
}
}
cout<<endl;
}
else
cfn;
}
int main()
{
// freopen("tst.txt","r",stdin);
// freopen("sans.txt","w",stdout);
IOS;
_t_=1;
// cin>>_t_;
while(_t_--)
solve();
QwQ;
}