Description
你的任务是将一群人分到两个队伍中,使得:
1、每个人都属于一个队伍。
2、每个队伍至少有一个人。
3、每个队伍的任意一个人都认识其他人。
4、两支队伍的人数尽可能接近。
这个任务可能有多组解,你可以输出任意一种。
注意:认识是单向的且没有传递性。
Input
第一行为一个整数N,表示总人数。
接下来为N行,每行多个整数x,第i + 1行描述编号为i的人认识x。每行以 0 结尾。
Output
如果无解输出−1;否则输出包含两行, 每行的第一个数字表示该队伍的总人数k,后面接着k个数字,表示被分到该队伍的人。
Sample Input
5
2 3 5 0
1 4 5 3 0
1 2 5 0
1 2 3 0
4 3 2 1 0
Sample Output
3 1 3 5
2 2 4
Data Constraint
对于分值为 30%的数据,N <= 15
对于剩余分值为 70%的数据,N <= 100
Solution
我们先把不能相连的弄出来
那显然他们要放在不同的集合
这样子搞一搞之后
我们就可以dp了
设一个0/1状态f[h][i][j]表示做完前h个小团块 第一个集合放i个 第二个集合放j个是否可行
dp的时候保留一下方案即可
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define fd(i,a,b) for(i=a;i>=b;i--)
using namespace std;
int n,i,j,stm,h,k,cnt1,cnt2,a,b,f[105][105][105],x,y,xx,yy,k1,k2,z;
int aa[105][105],bz[105],g[105][2],un[105][105],pr[105],w[105],w1[105];
struct edge{
int x,y;
} bf[105][105][105];
int read(){
int sum=0;
char c=getchar();
while (c<'0'||c>'9') c=getchar();
while (c>='0'&&c<='9'){
sum=sum*10+c-'0';
c=getchar();}
return sum;
}
void dfs(int x){
int i,y;
fo(i,1,un[x][0]){
y=un[x][i];
if (bz[y]){
if (bz[y]==bz[x]) { printf("-1\n"); exit(0);}
} else {
bz[y]=(bz[x]==stm)?stm+1:stm;
if (bz[y]==stm) cnt1++; else cnt2++;
dfs(y);}
}
}
int main(){
//freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
n=read();
fo(i,1,n){
k=read();
while (k) aa[i][k]=1,k=read();}
fo(i,1,n)
fo(j,1,n)
if (i!=j&&(!aa[i][j]||!aa[j][i])) un[i][++un[i][0]]=j;
fo(i,1,n){
if (bz[i]) continue;
stm+=2,cnt2=0,cnt1=1,bz[i]=stm,dfs(i);
g[++h][0]=cnt1,g[h][1]=cnt2;
pr[h]=stm;}
f[0][0][0]=1;
fo(i,1,h)
fo(a,0,n)
fo(b,0,n) {
if (a+g[i][0]<=n&&b+g[i][1]<=n){
f[i][a+g[i][0]][b+g[i][1]]|=f[i-1][a][b];
if (f[i-1][a][b]) {
bf[i][a+g[i][0]][b+g[i][1]].x=a;
bf[i][a+g[i][0]][b+g[i][1]].y=b;}
}
if (a+g[i][1]<=n&&b+g[i][0]<=n){
f[i][a+g[i][1]][b+g[i][0]]|=f[i-1][a][b];
if (f[i-1][a][b]){
bf[i][a+g[i][1]][b+g[i][0]].x=a;
bf[i][a+g[i][1]][b+g[i][0]].y=b;}
}
}
fd(i,n/2,1)
if (f[h][i][n-i]){
x=i,y=n-i;
fd(j,h,1){
xx=bf[j][x][y].x,yy=bf[j][x][y].y;
k1=pr[j],k2=k1+1;
if (x-xx==g[j][1]) swap(k1,k2);
fo(z,1,n) if (bz[z]==k1) w[++w[0]]=z;
else if (bz[z]==k2) w1[++w1[0]]=z;
x=xx,y=yy;
}
fo(j,0,w[0]) printf("%d ",w[j]);
printf("\n");
fo(j,0,w1[0]) printf("%d ",w1[j]);
printf("\n");
return 0;
}
}