UOJ #596. 罪犯分组
作者:互联网
【题目描述】:
B 城有一座监狱,一共关押着N 名罪犯,编号分别为1-N。
他们的关系十分不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。
在详细考察了N 名罪犯间的矛盾关系后,警察局长发现罪犯之间的矛盾关系可以用一个N 个点M 条边的无向图来表示:如果x 到y 有一条边,表示罪犯x 和罪犯y 有矛盾。
现在警察局长要把这些罪犯分成一些小组,每名罪犯属于且仅属于一个小组。
为了开展活动顺利,要求每个小组内最多有K 对罪犯有矛盾,同时为了管理方便,警察局长希望最小化分成的小组数量。
那么,应如何分配罪犯,才能使分成的小组数量最少?这个最小值是多少?
【输入描述】:
第一行3个整数,N,M,K;
以下M行,每行两个数字x,y。表示x和y之间有矛盾。
【输出描述】:
输出一行一个值,表示最少的分组数量。
【样例输入】:
3 3 1
1 2
2 3
1 3
【样例输出】:
2
【时间限制、数据范围及描述】:
时间:1s 空间:256M
对于每个测试点,N分别为:2,4,6,8,10,12,14,15,16,16;
0≤M,K≤N(N-1)/2;
保证是一个无自环、无重边的无向图。
本题设f(S)为集合S需要的最小分组数。
则f(S)=min{ f(S−S0)+1 | S0⫋S,S0集合可分成1组 }
要枚举全集的所有子集的所有子集,时间复杂度是O(3^n)
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<deque>
using namespace std;
const int N=25,INF=0x3f3f3f3f;
int n,m,k,f[1<<N],map[N][N];
bool lim[1<<N];
int main(){
int x,y;
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
map[x][y]=map[y][x]=1;
}
for(int s=1;s<(1<<n);s++){
int cnt=0;
for(int i=1;i<=n;i++){
for(int j=i+1;j<=n;j++){
if(map[i][j]&&(s&(1<<(i-1)))&&(s&(1<<(j-1)))){
++cnt;
}
}
}
if(cnt>k){
lim[s]=false;
}
else{
lim[s]=true;
}
}
for(int s=1;s<(1<<n);s++){
if(lim[s]){
f[s]=1;
}
else{
f[s]=INF;
}
for(int s1=(s-1)&s;s1>0;s1=(s1-1)&s){
if(lim[s1]){
f[s]=min(f[s],f[s-s1]+1);
}
}
}
printf("%d\n",f[(1<<n)-1]);
return 0;
}
标签:S0,596,int,s1,小组,罪犯,分组,UOJ,include 来源: https://www.cnblogs.com/ukcxrtjr/p/11595207.html