[计蒜客20191103C] 分组
小 C 是 个学生的老师,他现在要把所有学生分成两组,他会按照以下这些要求:
1、如果两个同学是好朋友那么他们就不会被分到同一组
2、小 C 想最小化两组人数差值
现在请你写一个程序来帮助小 C 分组,数据保证有合法的方案,如果有多种合法方案则输出字典序最小的
输入格式
第一行两个整数分别表示
接下来行,每行两个整数表示 是好朋友
输出格式
如果第 位学生被分到第 1 组则第 位为 1,反之为 2
如果有多种合法方案则输出字典序最小的方案
数据范围
对于 的数据,
对于 的数据,
对于 的数据,
输出时每行末尾的多余空格,不影响答案正确性
样例输入
6 4
1 2
1 3
4 6
4 5
样例输出
122211
如果把关系看成图论里的边,那么边相连的两个同学不能在一组,所以每一个连通块是一个二分图。就可以把一个连通块分成两部分学生,两部分学生一边是第一组,一边是第二组。
可以搜索考虑每一组的选择情况。把所有连通块按照最小编号的学生排完序后,为了让字典序尽量小,每个连通块优先让最小编号更小的那一部分选择1,其余选择2.过程中记录两组的差值。
发现搜索过程无后效性,记录为前i个连通块差值为(防止负数)的情况是否枚举过。如果已经枚举过就不用再枚举一次了。复杂度O(n^2)
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,m,hd[N],t[N],idx=1,ans[N],v[N<<1][N<<1],k,ret=2e9,st[N],x,y;
struct edge{
int v,nxt;
}e[N<<8];
void add_edge(int u,int v,int z)
{
e[z]=(edge){v,hd[u]};
hd[u]=z;
}
vector<int>g[N+N];
void dfs(int x,int y)
{
t[x]=y,g[y].push_back(x);
for(int i=hd[x];i;i=e[i].nxt)
if(!t[e[i].v])
dfs(e[i].v,y^1);
}
void sou(int x,int y)
{
if(v[x][y+1000])
return;
if(x>idx)
{
if(abs(y)<ret)
memcpy(ans,st,sizeof(st)),ret=abs(y);
return;
}
v[x][y+1000]=1;
for(int i=0;i<g[x].size();i++)
st[g[x][i]]=1;
for(int i=0;i<g[x|1].size();i++)
st[g[x|1][i]]=2;
sou(x+2,y+g[x].size()-g[x|1].size());
for(int i=0;i<g[x].size();i++)
st[g[x][i]]=2;
for(int i=0;i<g[x|1].size();i++)
st[g[x|1][i]]=1;
sou(x+2,y+g[x|1].size()-g[x].size());
}
int main()
{
scanf("%d%d",&n,&m),k=n+n+1;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
add_edge(y,x,i<<1);
add_edge(x,y,i<<1|1);
}
for(int i=1;i<=n;i++)
{
if(!t[i])
{
dfs(i,++idx);
++idx;
}
}
sou(2,0);
for(int i=1;i<=n;i++)
printf("%d",ans[i]);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!